Skip to content

Overview

Viewing v1— superseded by v2

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

Authentication

Every endpoint requires a Bearer token in the Authorization header, except the ones a client reads while deciding whether to integrate at all: openapi.json, versioning, and the interactive docs.

Authorization: Bearer <token>

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

  1. Log in to 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 9457 Problem Details with content type application/problem+json:

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

Branch on type, not on title or detail — those are prose and may be reworded. type is a stable opaque identifier whose last path segment is the machine-readable error code; it is not a live URL and does not resolve to a page. Documentation lives at docs.layer.ai.

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.

Idempotency

A lost response is indistinguishable from a request that never arrived, and retrying a generation spends Creative Units again. Send an idempotency key on any unsafe request and a retry is free:

Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7

The first request with a given key executes. Every later request with the same key returns that first response, with Idempotent-Replayed: true added, without executing anything. Any opaque string up to 255 characters works; a UUID per logical operation is the usual choice. Keys are scoped to your credential’s owner and replayable for 24 hours.

Three cases are not replays:

  • A different request under the same key returns 422 IDEMPOTENCY_KEY_REUSED. The key covers the method, path, and body it was first used with, so this is a client bug rather than a retry — returning some other request’s result would be worse than an error.
  • A retry while the original is still running returns 409 IDEMPOTENT_REQUEST_IN_PROGRESS with Retry-After, because the result does not exist yet.
  • A failed request does not reserve its key. Nothing was spent, so a retry executes rather than replaying the error.

Keys on safe methods are ignored — GET is already repeatable.

Rate limits

Quotas are per user and apply to the compute operations that spend Creative Units: starting a generation and starting a training run.

Every response describes the quotas in force, including one that rejected you for having no credential — a client that has not authenticated yet is the one that most needs to know what budget it will be planning against:

RateLimit-Policy: "generation";q=60;w=60, "generation-video";q=30;w=60, "training";q=10;w=3600

A quota named after a modality narrows the one it extends: a video generation spends from both generation and generation-video, so the tighter of the two decides.

Once you are authenticated, responses from the operations a quota governs also report what is left of it:

RateLimit: "generation";r=57;t=3
RateLimit-Limit: 60
RateLimit-Remaining: 57
RateLimit-Reset: 3

RateLimit-Policy and RateLimit are the standard structured fields — q is the quota, w the window in seconds, r the units left, t the seconds until the quota is fully restored. The RateLimit-Limit/-Remaining/-Reset triple repeats the tightest quota for clients that parse the older convention.

Exceeding a quota returns 429 with a Retry-After header; wait that many seconds before retrying.

Versioning and deprecation

The API version is the first path segment. /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.

Backward-compatible additions — a new endpoint, a new optional request field, a new response field — ship into an existing version without notice. Anything that could break a client gets a new version instead.

Nothing is withdrawn without notice. When an operation or a version is deprecated:

  1. It is marked deprecated: true in openapi.json.
  2. Every response from it carries Deprecation (RFC 9745) with the date it was deprecated, Sunset (RFC 8594) with the earliest date it may stop working, and a Link header with rel="deprecation" to this policy and rel="successor-version" to its replacement.
  3. It keeps working until the sunset date, which is at least 180 days after the deprecation date.

Poll openapi.json or watch for Deprecation on your own traffic — both carry the same timeline.

Information

  • OpenAPI version: 3.1.0

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

OAuth 2.0 authorization against Layer’s authorization server. Discovery metadata for this resource is published at https://api.app.layer.ai/.well-known/oauth-protected-resource (RFC 9728), and the authorization server’s own metadata at https://auth.app.layer.ai/.well-known/oauth-authorization-server (RFC 8414).

Security scheme type: oauth2

Flow type: authorizationCode

Authorization URL: https://auth.app.layer.ai/authorize

Token URL: https://auth.app.layer.ai/oauth/token

Refresh URL: https://auth.app.layer.ai/oauth/token

Flow type: clientCredentials

Token URL: https://auth.app.layer.ai/oauth/token

Refresh URL: https://auth.app.layer.ai/oauth/token