# Overview

## Layer REST API (v1) 1.0.0

REST API for AI-powered game asset creation on the Layer platform.

## Authentication

All endpoints require a Bearer token in the `Authorization` header:

```
Authorization: Bearer <token>
```

### Personal Access Tokens (recommended)

The simplest way to authenticate is with a Personal Access Token (PAT):

1. Log in to [app.layer.ai](https://app.layer.ai)
2. Go to **Settings > Personal Access Tokens**
3. Click **Create Token**, give it a name, and copy the token value
4. Pass it as `Authorization: Bearer <your-pat-token>`

PATs are long-lived and ideal for scripts, CI pipelines, and partner integrations.

### OAuth2 (browser-based)

For browser-based applications, use the Auth0 OAuth2 flow. Redirect users to the Layer login page, exchange the authorization code for a JWT access token, and use it as `Authorization: Bearer <jwt>`.

## Creative Units

Generations consume Creative Units (CUs). Use the estimate endpoints to check cost before executing. Check workspace balance via `GET /v1/workspaces/{id}`.

## Pagination

List endpoints support cursor-based pagination via `limit` and `cursor` query parameters. Responses include a `pagination` object with `next_cursor`, `has_more_results`, and `total_count`. Cursors are opaque — do not parse or construct them.

## Errors

All errors return [RFC 7807 Problem Details](https://tools.ietf.org/html/rfc7807):

```
{
  "type": "https://api.layer.ai/errors/ERROR_CODE",
  "title": "Human-readable title",
  "status": 404,
  "detail": "Detailed description of what went wrong."
}
```

Common status codes: `401` (unauthenticated), `403` (forbidden), `404` (not found), `422` (invalid input), `429` (rate limited).

Creative Units are not checked when a run is submitted, so an underfunded workspace does not fail at submission time. Call the estimate endpoint and read `has_sufficient_creative_units` to check up front; otherwise the run is accepted and then reaches a terminal `FAILED` state with `error_code` `INSUFFICIENT_BALANCE`.

## Versioning

`/v1` and `/v2` are both stable and served together; v1 routes are unaffected by v2.

`/v2` is a complete surface — every resource is reachable under it, so a client can pin `/v2` and never fall back. It differs from v1 in the generation surface: inference runs take reference sets — trained subjects, styles, and characters — alongside a base model, and the v1 `/models` catalog is split into `/base-models` and `/reference-sets`.

Every other resource is the same endpoint under both prefixes: identical handler, request body, and response shape. Their v2 operation ids carry a `V2` suffix so generated clients get one symbol per published path.

Information

* OpenAPI version: `3.1.0`

## Operations

GET

[/v1/workspaces/{workspace\_id}/models](/docs/v1/rest-api/operations/listmodels)

GET

[/v1/workspaces/{workspace\_id}/models/{model\_id}](/docs/v1/rest-api/operations/getmodel)

POST

[/v1/workspaces/{workspace\_id}/inferences/estimate](/docs/v1/rest-api/operations/estimateinferenceprice)

POST

[/v1/workspaces/{workspace\_id}/inferences](/docs/v1/rest-api/operations/executeinference)

GET

[/v1/workspaces/{workspace\_id}/inferences/{inference\_id}](/docs/v1/rest-api/operations/getinferencerun)

POST

[/v1/workspaces/{workspace\_id}/inferences/{inference\_id}/cancel](/docs/v1/rest-api/operations/cancelinference)

POST

[/v1/workspaces/{workspace\_id}/reference-sets](/docs/v1/rest-api/operations/createreferenceset)

POST

[/v1/workspaces/{workspace\_id}/training-runs/estimate](/docs/v1/rest-api/operations/estimatetrainingprice)

GET

[/v1/workspaces/{workspace\_id}/training-runs](/docs/v1/rest-api/operations/listtrainingruns)

POST

[/v1/workspaces/{workspace\_id}/training-runs](/docs/v1/rest-api/operations/starttrainingrun)

GET

[/v1/workspaces/{workspace\_id}/training-runs/{training\_run\_id}](/docs/v1/rest-api/operations/gettrainingrun)

POST

[/v1/workspaces/{workspace\_id}/training-runs/{training\_run\_id}/cancel](/docs/v1/rest-api/operations/canceltrainingrun)

GET

[/v1/workspaces/{workspace\_id}/training-runs/{training\_run\_id}/model](/docs/v1/rest-api/operations/gettrainedmodel)

POST

[/v1/workspaces/{workspace\_id}/files/upload-url](/docs/v1/rest-api/operations/requestfileuploadurl)

GET

[/v1/workspaces/{workspace\_id}/scoring-rules](/docs/v1/rest-api/operations/listscoringrules)

POST

[/v1/workspaces/{workspace\_id}/scores](/docs/v1/rest-api/operations/scorefiles)

GET

[/v1/workspaces/{workspace\_id}/files/{file\_id}/scores](/docs/v1/rest-api/operations/getfilescores)

GET

[/v1/workspaces/{workspace\_id}/workflows](/docs/v1/rest-api/operations/listworkflows)

POST

[/v1/workspaces/{workspace\_id}/workflows/{workflow\_id}/estimate](/docs/v1/rest-api/operations/estimateworkflowprice)

POST

[/v1/workspaces/{workspace\_id}/workflows/{workflow\_id}/runs](/docs/v1/rest-api/operations/executeworkflow)

GET

[/v1/workspaces/{workspace\_id}/workflows/{workflow\_id}/runs/{run\_id}](/docs/v1/rest-api/operations/getworkflowrun)

GET

[/v1/workspaces](/docs/v1/rest-api/operations/listworkspaces)

GET

[/v1/workspaces/{workspace\_id}](/docs/v1/rest-api/operations/getworkspace)

GET

[/v1/workspaces/{workspace\_id}/usage](/docs/v1/rest-api/operations/getworkspaceusage)

GET

[/v1/workspaces/{workspace\_id}/projects](/docs/v1/rest-api/operations/listprojects)

POST

[/v1/workspaces/{workspace\_id}/projects](/docs/v1/rest-api/operations/createproject)

GET

[/v1/workspaces/{workspace\_id}/projects/{project\_id}](/docs/v1/rest-api/operations/getproject)

DELETE

[/v1/workspaces/{workspace\_id}/projects/{project\_id}](/docs/v1/rest-api/operations/deleteproject)

PATCH

[/v1/workspaces/{workspace\_id}/projects/{project\_id}](/docs/v1/rest-api/operations/updateproject)

POST

[/v1/workspaces/{workspace\_id}/projects/{project\_id}/members](/docs/v1/rest-api/operations/addprojectmembers)

DELETE

[/v1/workspaces/{workspace\_id}/projects/{project\_id}/members/{user\_id}](/docs/v1/rest-api/operations/removeprojectmember)

GET

[/v1/workspaces/{workspace\_id}/members](/docs/v1/rest-api/operations/listworkspacemembers)

POST

[/v1/workspaces/{workspace\_id}/members](/docs/v1/rest-api/operations/inviteworkspacemember)

PATCH

[/v1/workspaces/{workspace\_id}/members/{user\_id}](/docs/v1/rest-api/operations/updateworkspacemember)

GET

[/v1/workspaces/{workspace\_id}/groups](/docs/v1/rest-api/operations/listgroups)

POST

[/v1/workspaces/{workspace\_id}/groups](/docs/v1/rest-api/operations/creategroup)

DELETE

[/v1/workspaces/{workspace\_id}/groups/{group\_id}](/docs/v1/rest-api/operations/deletegroup)

PATCH

[/v1/workspaces/{workspace\_id}/groups/{group\_id}](/docs/v1/rest-api/operations/updategrouprole)

GET

[/v1/workspaces/{workspace\_id}/groups/{group\_id}/members](/docs/v1/rest-api/operations/listgroupmembers)

POST

[/v1/workspaces/{workspace\_id}/groups/{group\_id}/members](/docs/v1/rest-api/operations/addgroupmember)

DELETE

[/v1/workspaces/{workspace\_id}/groups/{group\_id}/members/{user\_id}](/docs/v1/rest-api/operations/removegroupmember)

PUT

[/v1/workspaces/{workspace\_id}/groups/{group\_id}/usage-limit](/docs/v1/rest-api/operations/setgroupusagelimit)

DELETE

[/v1/workspaces/{workspace\_id}/groups/{group\_id}/usage-limit](/docs/v1/rest-api/operations/removegroupusagelimit)

## Authentication

### bearerAuth

Bearer authentication with a Layer Personal Access Token (PAT), prefixed `pat_`. Send it as `Authorization: Bearer <token>`. Create one in the app under Settings → Personal Access Tokens. An Auth0 session JWT is also accepted for first-party browser use.

**Security scheme type:** http
