{
  "name": "Layer Platform API",
  "description": "Programmatic access to Layer — generate and edit images, video, 3D, and audio assets, train custom styles, run node-based workflows, and manage workspaces.",
  "documentation_url": "https://www.layer.ai/docs",
  "interfaces": {
    "rest": {
      "title": "Layer REST API",
      "version": "1.0.0",
      "openapi_version": "3.1.0",
      "base_url": "https://api.app.layer.ai/api",
      "openapi_url": "https://www.layer.ai/openapi.json",
      "documentation_url": "https://www.layer.ai/docs/rest-api",
      "path_count": 41,
      "operation_count": 50,
      "authentication": {
        "methods": [
          {
            "type": "http",
            "scheme": "bearer",
            "credential": "personal_access_token",
            "self_serve": true,
            "description": "Bearer authentication with a Layer Personal Access Token (prefixed `pat_`), created by the user under Settings → Personal Access Tokens. Recommended for server-side integrations.",
            "instructions_url": "https://www.layer.ai/docs/authentication"
          },
          {
            "type": "oauth2",
            "scheme": "bearer",
            "credential": "access_token",
            "self_serve": true,
            "flow": "authorization_code",
            "pkce_required": true,
            "dynamic_client_registration": true,
            "description": "OAuth 2.0 authorization code flow with PKCE against the Layer authorization server. Used by MCP clients and browser-based apps; the issued access token is accepted by the REST API too.",
            "instructions_url": "https://www.layer.ai/docs/authentication#oauth-20",
            "authorization_server": {
              "issuer": "https://auth.app.layer.ai/",
              "metadata_url": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
              "openid_configuration_url": "https://auth.app.layer.ai/.well-known/openid-configuration",
              "authorization_endpoint": "https://auth.app.layer.ai/authorize",
              "token_endpoint": "https://auth.app.layer.ai/oauth/token",
              "registration_endpoint": "https://auth.app.layer.ai/oidc/register",
              "revocation_endpoint": "https://auth.app.layer.ai/oauth/revoke",
              "device_authorization_endpoint": "https://auth.app.layer.ai/oauth/device/code",
              "jwks_uri": "https://auth.app.layer.ai/.well-known/jwks.json",
              "grant_types_supported": [
                "authorization_code",
                "refresh_token"
              ],
              "scopes_supported": [
                "openid",
                "profile",
                "email",
                "offline_access"
              ],
              "code_challenge_methods_supported": [
                "S256"
              ],
              "dynamic_client_registration": true
            }
          }
        ],
        "challenge": {
          "status": 401,
          "header": "WWW-Authenticate",
          "description": "An unauthenticated REST request returns 401 with `WWW-Authenticate: Bearer`. An unauthenticated MCP request returns 401 with a `resource_metadata` parameter pointing at that server’s RFC 9728 protected-resource metadata."
        }
      },
      "permissions": {
        "model": "role-based",
        "description": "Layer authorizes every request from the calling user, not from the credential. Access is evaluated against that user's role in the target workspace (and, for project-scoped resources, their project membership). A request the user may not perform returns 403.",
        "documentation_url": "https://www.layer.ai/docs/authentication#permissions",
        "api_scopes_supported": [],
        "scoped_credentials_supported": false,
        "scoped_credentials_note": "A Personal Access Token inherits ALL of its creating user's permissions; there are no per-token scopes. To limit an integration, provision a dedicated Layer user and give that user only the workspace role and project membership it needs.",
        "roles": [
          "VIEWER",
          "MEMBER",
          "ADMIN",
          "OWNER"
        ],
        "general_rule": "GET operations require VIEWER in the target workspace. Operations that create, change, or delete state — or that start a run and therefore consume Creative Units — require at least MEMBER. Workspace and member administration requires ADMIN or OWNER."
      },
      "rate_limits": {
        "scope": "user",
        "description": "Generation is rate limited per user — the owner of the access token — not per workspace. List, get, and estimate endpoints are not rate limited, and workflow runs are not currently subject to the generation limits.",
        "documentation_url": "https://www.layer.ai/docs/rate-limits",
        "limits": [
          {
            "name": "generations",
            "description": "Generations across all modalities",
            "limit": 60,
            "window_seconds": 60
          },
          {
            "name": "video-generations",
            "description": "Video generations, counted in addition to the all-modality limit",
            "limit": 30,
            "window_seconds": 60
          }
        ],
        "exceeded": {
          "status": 429,
          "error_code": "RATE_LIMITED",
          "media_type": "application/problem+json",
          "retry_after_header": "Retry-After",
          "description": "Exceeding a limit returns 429 with a `Retry-After` header in seconds. Wait for that interval, with jitter if you run several workers, before retrying."
        },
        "response_headers": {
          "ratelimit": {
            "supported": false,
            "specification": "https://www.rfc-editor.org/rfc/rfc9331"
          },
          "x_ratelimit": {
            "supported": false
          },
          "retry_after": {
            "supported": true,
            "specification": "https://www.rfc-editor.org/rfc/rfc9110#field.retry-after"
          }
        }
      },
      "versioning": {
        "style": "uri-path",
        "description": "The REST API is path-versioned under the base URL: /v1 is the stable surface, /v2 extends inference generation with reference sets and adds the base-model and reference-set catalogs. Both are served together; v1 routes are unaffected by v2.",
        "current_versions": [
          "v1",
          "v2"
        ],
        "documentation_url": "https://www.layer.ai/docs/versioning",
        "deprecation_policy": {
          "url": "https://www.layer.ai/docs/deprecation",
          "signals": [
            {
              "name": "Deprecation header",
              "specification": "https://www.rfc-editor.org/rfc/rfc9745",
              "description": "A deprecated operation returns `Deprecation: @<unix-timestamp>` — the moment it became deprecated. It keeps working until its sunset date."
            },
            {
              "name": "Sunset header",
              "specification": "https://www.rfc-editor.org/rfc/rfc8594",
              "description": "A deprecated operation returns `Sunset: <HTTP-date>` — the moment it stops responding. Treat this as the migration deadline."
            },
            {
              "name": "Link: rel=\"deprecation\"",
              "specification": "https://www.rfc-editor.org/rfc/rfc9745#name-the-deprecation-link-relati",
              "description": "A `Link` header with `rel=\"deprecation\"` points at the migration notes."
            },
            {
              "name": "OpenAPI deprecated flag",
              "specification": "https://spec.openapis.org/oas/v3.1.0#fixed-fields-7",
              "description": "The operation is marked `deprecated: true` in /openapi.json, with `x-layer-sunset` carrying the same date as the Sunset header."
            }
          ],
          "minimum_notice_days": 90,
          "breaking_change_policy": "Breaking changes ship under a new version prefix rather than changing an existing one. New endpoints, new optional request fields, new response fields, and new enum values are non-breaking — parse responses leniently and ignore what you do not recognise."
        }
      },
      "webhooks": {
        "supported": false,
        "alternative": "poll",
        "description": "Layer does not deliver webhooks. Long-running generations are polled: start a run, then poll it on the `poll_interval_seconds` the response returns.",
        "documentation_url": "https://www.layer.ai/docs/async-jobs"
      },
      "error_format": {
        "media_type": "application/problem+json",
        "specification": "https://www.rfc-editor.org/rfc/rfc9457",
        "description": "Errors are RFC 9457 problem details with `type`, `title`, `status`, and `detail`. Common statuses: 401 unauthenticated, 403 forbidden, 404 not found, 422 invalid input, 429 rate limited.",
        "documentation_url": "https://www.layer.ai/docs/errors"
      },
      "pagination": {
        "style": "cursor",
        "parameters": [
          "limit",
          "cursor"
        ],
        "description": "List endpoints return a `pagination` object with `next_cursor`, `has_more_results`, and `total_count`. Cursors are opaque — do not parse or construct them.",
        "documentation_url": "https://www.layer.ai/docs/pagination"
      },
      "cost_model": {
        "unit": "Creative Unit (CU)",
        "description": "Generations consume Creative Units. Call the matching estimate endpoint and read `has_sufficient_creative_units` before executing a run.",
        "pricing_url": "https://www.layer.ai/pricing",
        "machine_readable_pricing_url": "https://www.layer.ai/pricing.md"
      }
    },
    "mcp": [
      {
        "id": "creative",
        "name": "Layer MCP Server",
        "description": "Generate and edit images, video, 3D, and audio; run Blueprint workflows; train styles; assemble video timelines; upload and score files.",
        "endpoint": "https://mcp.app.layer.ai/mcp",
        "transport": "streamable-http",
        "authentication": {
          "type": "oauth2",
          "flow": "authorization_code",
          "pkce_required": true,
          "dynamic_client_registration": true,
          "authorization_servers": [
            "https://auth.app.layer.ai/"
          ],
          "authorization_server_metadata": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
          "scopes_supported": [
            "openid",
            "profile",
            "email",
            "offline_access"
          ],
          "description": "Unauthenticated requests return 401 with a `WWW-Authenticate: Bearer resource_metadata=…` challenge pointing at the RFC 9728 protected-resource metadata for that server. Follow it to the authorization server, register dynamically, and run the authorization-code + PKCE flow.",
          "protected_resource_metadata": "https://mcp.app.layer.ai/.well-known/oauth-protected-resource/mcp"
        },
        "tool_count": 36,
        "tools": [
          "cancel_inference",
          "cancel_training_run",
          "cancel_workflow_run",
          "create_reference_set",
          "estimate_forge_price",
          "estimate_training_price",
          "estimate_video_timeline_price",
          "estimate_workflow_price",
          "execute_forge",
          "execute_workflow",
          "get_base_model",
          "get_base_model_recommendations",
          "get_file_scores",
          "get_forge_instructions",
          "get_forge_run",
          "get_generation_run",
          "get_instructions",
          "get_project",
          "get_reference_set",
          "get_trained_model",
          "get_training_status",
          "get_workflow_instructions",
          "get_workflow_run",
          "get_workspace",
          "list_base_models",
          "list_output_scoring_rules",
          "list_projects",
          "list_reference_sets",
          "list_training_runs",
          "list_workflows",
          "list_workspaces",
          "render_video_timeline",
          "request_file_upload_url",
          "score_files",
          "start_training",
          "upload_file"
        ],
        "documentation_url": "https://www.layer.ai/docs/mcp",
        "setup_url": "https://www.layer.ai/docs/mcp/setup"
      },
      {
        "id": "management",
        "name": "Layer Management MCP Server",
        "description": "Administer a workspace: projects, groups, members, roles, usage limits, and Creative Unit consumption. Kept separate so admin tools do not crowd the creative toolset.",
        "endpoint": "https://mcp.app.layer.ai/mcp-management",
        "transport": "streamable-http",
        "authentication": {
          "type": "oauth2",
          "flow": "authorization_code",
          "pkce_required": true,
          "dynamic_client_registration": true,
          "authorization_servers": [
            "https://auth.app.layer.ai/"
          ],
          "authorization_server_metadata": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
          "scopes_supported": [
            "openid",
            "profile",
            "email",
            "offline_access"
          ],
          "description": "Unauthenticated requests return 401 with a `WWW-Authenticate: Bearer resource_metadata=…` challenge pointing at the RFC 9728 protected-resource metadata for that server. Follow it to the authorization server, register dynamically, and run the authorization-code + PKCE flow.",
          "protected_resource_metadata": "https://mcp.app.layer.ai/.well-known/oauth-protected-resource/mcp"
        },
        "tool_count": 22,
        "tools": [
          "add_group_member",
          "add_project_members",
          "create_group",
          "create_project",
          "delete_group",
          "delete_project",
          "get_project",
          "get_workspace_usage",
          "invite_member",
          "list_group_members",
          "list_groups",
          "list_projects",
          "list_workspace_members",
          "list_workspaces",
          "reactivate_member",
          "remove_group_member",
          "remove_group_usage_limit",
          "remove_project_member",
          "set_group_usage_limit",
          "suspend_member",
          "update_group_role",
          "update_project"
        ],
        "documentation_url": "https://www.layer.ai/docs/mcp/management",
        "setup_url": "https://www.layer.ai/docs/mcp/management/setup"
      }
    ]
  },
  "onboarding": {
    "self_serve_signup": {
      "supported": true,
      "url": "https://next.app.layer.ai/"
    },
    "sales_contact_required": false,
    "free_tier": {
      "supported": true,
      "type": "starter_credits",
      "time_limited": false,
      "description": "Creating a Layer account is free and includes a one-off grant of Creative Units, enough to run real generations before subscribing. It is not a time-limited trial and it does not expire into a locked account. Continued generation needs a subscription (from $10/month) or a CU pack; there are no seat fees or feature gates.",
      "url": "https://www.layer.ai/pricing"
    },
    "self_serve_credentials": {
      "supported": true,
      "type": "personal_access_token",
      "description": "Create a Personal Access Token (prefixed `pat_`) yourself in the app under Settings → Personal Access Tokens. No approval step and no sales contact. The token value is shown once. There is no REST endpoint that mints, lists, or revokes tokens.",
      "url": "https://next.app.layer.ai/",
      "documentation_url": "https://www.layer.ai/docs/authentication"
    },
    "oauth_connection": {
      "supported": true,
      "description": "MCP clients connect over OAuth 2.0 with PKCE and dynamic client registration — no API key and no pre-registered client. Point the client at an MCP endpoint and complete the browser sign-in it prompts for.",
      "documentation_url": "https://www.layer.ai/docs/mcp/setup"
    },
    "sandbox": {
      "supported": false,
      "description": "There is no separate sandbox or test environment. Estimate endpoints (and their MCP equivalents) price a run without executing it, which is the supported way to rehearse a call for free.",
      "documentation_url": "https://www.layer.ai/docs/creative-units"
    },
    "cost_control": "Every generation has a matching estimate operation. Call it and read `has_sufficient_creative_units` before executing a run."
  },
  "developer_resources": [
    {
      "name": "Layer developer documentation",
      "url": "https://www.layer.ai/docs",
      "type": "text/html",
      "description": "Home of the Layer REST API, MCP servers, and integration guides."
    },
    {
      "name": "Layer API quickstart",
      "url": "https://www.layer.ai/docs/quickstart",
      "type": "text/html",
      "description": "Authenticate, pick a model, estimate cost, generate, and fetch results."
    },
    {
      "name": "Layer API authentication",
      "url": "https://www.layer.ai/docs/authentication",
      "type": "text/html",
      "description": "Personal Access Tokens, OAuth 2.0, and the workspace-role permission model."
    },
    {
      "name": "Layer REST API reference",
      "url": "https://www.layer.ai/docs/rest-api",
      "type": "text/html",
      "description": "Every REST endpoint, generated from the OpenAPI description."
    },
    {
      "name": "Layer OpenAPI description",
      "url": "https://www.layer.ai/openapi.json",
      "type": "application/json",
      "description": "Machine-readable Layer REST API surface (OpenAPI 3.1, base URL https://api.app.layer.ai/api)."
    },
    {
      "name": "Layer API index",
      "url": "https://www.layer.ai/api/index.json",
      "type": "application/json",
      "description": "REST and MCP entry points, OAuth discovery, rate limits, versioning, onboarding."
    },
    {
      "name": "Layer API catalog",
      "url": "https://www.layer.ai/.well-known/api-catalog",
      "type": "application/linkset+json",
      "description": "RFC 9727 catalog of every Layer API, as an RFC 9264 linkset."
    },
    {
      "name": "Layer MCP server",
      "url": "https://www.layer.ai/mcp",
      "type": "text/html",
      "description": "Connect Claude, Cursor, VS Code, Codex, or any MCP client to Layer."
    },
    {
      "name": "Layer MCP manifest",
      "url": "https://www.layer.ai/.well-known/mcp",
      "type": "application/json",
      "description": "Machine-readable manifest of both Layer MCP servers, their transport and tools."
    },
    {
      "name": "Layer MCP setup guide",
      "url": "https://www.layer.ai/docs/mcp/setup",
      "type": "text/html",
      "description": "Per-client install instructions for the Layer MCP server."
    },
    {
      "name": "Layer API rate limits",
      "url": "https://www.layer.ai/docs/rate-limits",
      "type": "text/html",
      "description": "Generation rate limits, 429 handling, and which response headers Layer sends."
    },
    {
      "name": "Layer API versioning",
      "url": "https://www.layer.ai/docs/versioning",
      "type": "text/html",
      "description": "How the REST API is versioned and what counts as a breaking change."
    },
    {
      "name": "Layer API deprecation policy",
      "url": "https://www.layer.ai/docs/deprecation",
      "type": "text/html",
      "description": "Deprecation and Sunset headers, notice period, and how removals are announced."
    },
    {
      "name": "Layer API errors",
      "url": "https://www.layer.ai/docs/errors",
      "type": "text/html",
      "description": "RFC 9457 problem details, error codes, and how to recover from each."
    },
    {
      "name": "Layer OAuth authorization server metadata",
      "url": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
      "type": "application/json",
      "description": "RFC 8414 metadata for the Layer authorization server (PKCE, dynamic registration)."
    }
  ],
  "discovery": {
    "api_catalog": "https://www.layer.ai/.well-known/api-catalog",
    "openapi": "https://www.layer.ai/openapi.json",
    "mcp_manifest": "https://www.layer.ai/.well-known/mcp",
    "oauth_authorization_server": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
    "oauth_protected_resource": "https://mcp.app.layer.ai/.well-known/oauth-protected-resource/mcp",
    "sitemap": "https://www.layer.ai/sitemap-index.xml",
    "llms_txt": "https://www.layer.ai/llms.txt",
    "llms_full_txt": "https://www.layer.ai/llms-full.txt",
    "docs_llms_txt": "https://www.layer.ai/docs/llms.txt",
    "robots_txt": "https://www.layer.ai/robots.txt"
  },
  "content_negotiation": {
    "description": "Marketing and documentation pages are also published as Markdown. Request the same path with `Accept: text/markdown`, or append `.md` to the path.",
    "specification": "https://acceptmarkdown.com",
    "example": "https://www.layer.ai/pricing.md"
  },
  "errors": {
    "404": {
      "type": "https://www.layer.ai/docs/errors#error-not-found",
      "title": "The requested path does not exist on www.layer.ai.",
      "status": 404,
      "detail": "Discover valid paths via /sitemap-index.xml, /llms.txt, or /openapi.json.",
      "code": "not_found",
      "message": "The requested path does not exist on www.layer.ai.",
      "resolution": "Discover valid paths via /sitemap-index.xml, /llms.txt, or /openapi.json.",
      "documentation_url": "https://www.layer.ai/docs/rest-api",
      "links": {
        "home": "https://www.layer.ai/",
        "sitemap": "https://www.layer.ai/sitemap-index.xml",
        "llms_txt": "https://www.layer.ai/llms.txt",
        "api_catalog": "https://www.layer.ai/.well-known/api-catalog",
        "openapi": "https://www.layer.ai/openapi.json",
        "api_index": "https://www.layer.ai/api/index.json",
        "docs": "https://www.layer.ai/docs",
        "api_reference": "https://www.layer.ai/docs/rest-api"
      }
    },
    "406": {
      "type": "https://www.layer.ai/docs/errors#error-not-acceptable",
      "title": "No representation of this resource matches the request Accept header.",
      "status": 406,
      "detail": "Request text/html, text/markdown, or application/json.",
      "code": "not_acceptable",
      "message": "No representation of this resource matches the request Accept header.",
      "resolution": "Request text/html, text/markdown, or application/json.",
      "documentation_url": "https://www.layer.ai/docs/rest-api",
      "links": {
        "home": "https://www.layer.ai/",
        "sitemap": "https://www.layer.ai/sitemap-index.xml",
        "llms_txt": "https://www.layer.ai/llms.txt",
        "api_catalog": "https://www.layer.ai/.well-known/api-catalog",
        "openapi": "https://www.layer.ai/openapi.json",
        "api_index": "https://www.layer.ai/api/index.json",
        "docs": "https://www.layer.ai/docs",
        "api_reference": "https://www.layer.ai/docs/rest-api"
      }
    }
  }
}
