{
  "name": "Layer — agent onboarding",
  "description": "How an automated client gets from zero to a first authenticated Layer API call without talking to a human. Every URL here is public; none of them requires a form, a demo, or a sales conversation.",
  "sales_contact_required": false,
  "signup": {
    "supported": true,
    "url": "https://next.app.layer.ai/"
  },
  "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"
  },
  "credentials": {
    "rest": {
      "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",
      "token_prefix": "pat_",
      "header": "Authorization: Bearer <token>",
      "programmatic_creation": {
        "supported": false,
        "description": "No REST endpoint creates, lists, or revokes a token. An agent needs one supplied once — from a secret manager, for example — after which every documented operation is available to it."
      },
      "permissions": {
        "model": "role-based",
        "scoped_credentials_supported": false,
        "description": "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.",
        "documentation_url": "https://www.layer.ai/docs/authentication#permissions"
      }
    },
    "oauth": {
      "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",
      "type": "oauth2",
      "flow": "authorization_code",
      "pkce_required": true,
      "dynamic_client_registration": true,
      "authorization_server_metadata": "https://auth.app.layer.ai/.well-known/oauth-authorization-server",
      "servers": [
        {
          "id": "creative",
          "name": "Layer MCP Server",
          "endpoint": "https://mcp.app.layer.ai/mcp",
          "setup_url": "https://www.layer.ai/docs/mcp/setup"
        },
        {
          "id": "management",
          "name": "Layer Management MCP Server",
          "endpoint": "https://mcp.app.layer.ai/mcp-management",
          "setup_url": "https://www.layer.ai/docs/mcp/management/setup"
        }
      ]
    }
  },
  "test_environment": {
    "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",
    "base_url": "https://api.app.layer.ai/api",
    "dry_run": {
      "consumes_credits": false,
      "description": "Every generation family has an estimate operation that validates the request and returns its Creative Unit cost plus `has_sufficient_creative_units`, without starting a run. One call exercises authentication, workspace access, the model id, and the parameter shape end to end.",
      "operations": [
        {
          "method": "POST",
          "path": "/v1/workspaces/{workspace_id}/inferences/estimate",
          "operation_id": "estimateInferencePrice",
          "summary": "Estimate inference price"
        },
        {
          "method": "POST",
          "path": "/v2/workspaces/{workspace_id}/inferences/estimate",
          "operation_id": "estimateInferencePriceV2",
          "summary": "Estimate inference price"
        },
        {
          "method": "POST",
          "path": "/v1/workspaces/{workspace_id}/training-runs/estimate",
          "operation_id": "estimateTrainingPrice",
          "summary": "Estimate training price"
        },
        {
          "method": "POST",
          "path": "/v2/workspaces/{workspace_id}/training-runs/estimate",
          "operation_id": "estimateTrainingPriceV2",
          "summary": "Estimate training price"
        },
        {
          "method": "POST",
          "path": "/v1/workspaces/{workspace_id}/workflows/{workflow_id}/estimate",
          "operation_id": "estimateWorkflowPrice",
          "summary": "Estimate workflow price"
        },
        {
          "method": "POST",
          "path": "/v2/workspaces/{workspace_id}/workflows/{workflow_id}/estimate",
          "operation_id": "estimateWorkflowPriceV2",
          "summary": "Estimate workflow price"
        }
      ]
    },
    "cost_control": "Every generation has a matching estimate operation. Call it and read `has_sufficient_creative_units` before executing a run.",
    "credential_free_development": {
      "description": "The API description, the model catalog, and pricing are published on this domain with no credential, so a client can be written and its requests validated before an account exists.",
      "endpoints": [
        "https://www.layer.ai/openapi.json",
        "https://www.layer.ai/api/index.json",
        "https://www.layer.ai/pricing.json"
      ]
    }
  },
  "zero_auth": {
    "description": "Public, credential-free endpoints on this domain. Each answers 200 with the stated media type, and every entry is verified against the running origin on each CI run.",
    "api_requires_auth": {
      "base_url": "https://api.app.layer.ai/api",
      "description": "The REST API has no anonymous operations: every endpoint requires a bearer token. An unauthenticated request answers 401 with an RFC 9457 problem document, so a client can detect the missing credential rather than guess.",
      "unauthenticated_status": 401,
      "unauthenticated_media_type": "application/problem+json"
    },
    "endpoints": [
      {
        "path": "/api/onboarding.json",
        "media_type": "application/json",
        "description": "This document — how to get from zero to an authenticated call."
      },
      {
        "path": "/api/index.json",
        "media_type": "application/json",
        "description": "Every Layer interface: REST and MCP entry points, authentication, permissions, rate limits, versioning, and policy."
      },
      {
        "path": "/openapi.json",
        "media_type": "application/json",
        "description": "Full OpenAPI 3.1 description of the REST API, suitable for function-calling."
      },
      {
        "path": "/.well-known/api-catalog",
        "media_type": "application/linkset+json",
        "description": "RFC 9727 API catalog: one anchor per Layer API, as an RFC 9264 linkset."
      },
      {
        "path": "/.well-known/ai-catalog.json",
        "media_type": "application/json",
        "description": "One entry point for an AI client: APIs, auth, policy, and the readable content surface."
      },
      {
        "path": "/.well-known/mcp",
        "media_type": "application/json",
        "description": "Both MCP servers, their transport, OAuth discovery, and full tool lists."
      },
      {
        "path": "/pricing.json",
        "media_type": "application/json",
        "description": "Per-model Creative Unit prices — cost a run before signing up."
      },
      {
        "path": "/pricing.md",
        "media_type": "text/markdown",
        "description": "The same pricing tables as Markdown."
      },
      {
        "path": "/llms.txt",
        "media_type": "text/plain",
        "description": "Site index for LLM clients (llmstxt.org)."
      },
      {
        "path": "/llms-full.txt",
        "media_type": "text/plain",
        "description": "Full text of the site in one document."
      },
      {
        "path": "/docs/llms.txt",
        "media_type": "text/plain",
        "description": "Developer documentation index for LLM clients."
      },
      {
        "path": "/sitemap-index.xml",
        "media_type": "text/xml",
        "description": "Every canonical URL on this domain."
      },
      {
        "path": "/404.json",
        "media_type": "application/problem+json",
        "description": "The RFC 9457 problem document this site returns for an unknown path."
      }
    ]
  },
  "quickstart": [
    {
      "step": 1,
      "action": "Read the API surface — no account needed",
      "url": "https://www.layer.ai/api/index.json"
    },
    {
      "step": 2,
      "action": "Create a workspace (self-serve, no sales contact)",
      "url": "https://next.app.layer.ai/"
    },
    {
      "step": 3,
      "action": "Create a Personal Access Token under Settings → Personal Access Tokens",
      "url": "https://www.layer.ai/docs/authentication"
    },
    {
      "step": 4,
      "action": "Verify the credential with an estimate call, which consumes no Creative Units",
      "method": "POST",
      "path": "/v1/workspaces/{workspace_id}/inferences/estimate"
    },
    {
      "step": 5,
      "action": "Subscribe or buy a CU pack once the starter Creative Units run out",
      "url": "https://www.layer.ai/pricing"
    }
  ],
  "human_escalation": {
    "required": false,
    "description": "Nothing above needs a human. Sales contact is for enterprise procurement — volume commitments, security review, MSAs — only.",
    "sales_url": "https://www.layer.ai/contact-sales",
    "enterprise_url": "https://www.layer.ai/enterprise"
  },
  "documentation": {
    "self_serve_access": "https://www.layer.ai/docs/self-serve-access",
    "quickstart": "https://www.layer.ai/docs/quickstart",
    "authentication": "https://www.layer.ai/docs/authentication",
    "creative_units": "https://www.layer.ai/docs/creative-units",
    "mcp_setup": "https://www.layer.ai/docs/mcp/setup",
    "errors": "https://www.layer.ai/docs/errors",
    "rate_limits": "https://www.layer.ai/docs/rate-limits"
  }
}
