> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simforge.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Register an AI agent

> auth.md Step 3. `service_auth`: an AI agent registers for the account `login_hint` names; show the person `claim.verification_uri` and `claim.user_code` (only that account, signed in with a verified email, can approve it), then poll the token endpoint with the claim grant. `identity_assertion`: an ID-JAG from a trusted agent provider (`issuer_not_enabled` while none is); it never creates or verifies an account. The first ID-JAG of a provider subject answers `401 interaction_required` with a claim ceremony; once the person confirmed the link, an ID-JAG answers an identity assertion valid for at most an hour. `401 login_required` when `auth_time` is missing or over an hour old. Refusals carry `detail.reason`. `anonymous` answers `anonymous_not_enabled`. 10 registrations per address per minute; 30 ID-JAGs per provider subject per 10 minutes.



## OpenAPI

````yaml /api-reference/openapi.json post /agent/identity
openapi: 3.1.0
info:
  title: SimForge Cloud API
  version: '2026-10-24'
  description: >-
    The public SimForge API: what `simforge --cloud`, `simforge login` and the
    Python client call. Authenticate with a bearer token: the access token
    `simforge login` stores, an AI agent's access token (its recipe is
    `/auth.md`), or an `sfk_` API key. A `/api/v1` 401 carries
    `WWW-Authenticate: Bearer
    resource_metadata="<host>/.well-known/oauth-protected-resource"`. `/api/v1`
    errors are an `ErrorEnvelope`; `/api/cli` and `/agent` errors are an OAuth
    error object.


    Versions: send `SimForge-Version: <date>` (2026-10-01, 2026-10-21,
    2026-10-22, 2026-10-23, 2026-10-24) and every `/api/v1` response is in that
    version's shape and names it in the same header; this document describes
    2026-10-24. A request without the header gets 2026-10-01, where an error's
    hint is `detail.hint` and `GET /api/v1/evaluations` names its rows `jobs`. A
    header that is not a date, or a date before 2026-10-01, is `400
    bad_request`. Every response also carries `SimForge-Cli-Minimum`: the oldest
    `simforge` CLI the server serves.


    Retries: from 2026-10-21, send a new `Idempotency-Key` (1-255 characters)
    with every POST, PUT, PATCH and DELETE, and the same key when retrying that
    request. The first request's answer is kept for 24 hours and a repeat gets
    it again with `Idempotent-Replayed: true`; the key with any other request,
    or while the first is still running, is `409 idempotency_conflict`
    (`retryable` while running). A 5xx answer is not kept. Creating an API key
    refuses a key (its secret is shown once).
  license:
    name: Apache-2.0
    identifier: Apache-2.0
servers:
  - url: https://dev.simforge.ai
    description: Development (dev.simforge.ai)
security: []
tags:
  - name: Sign-in
    description: >-
      `simforge login`: OAuth 2.0 device and browser sign-in for the CLI, the
      session behind a token. AI agents sign in through auth.md (`/auth.md`):
      register, a person approves, then the claim and JWT-bearer grants.
  - name: Account
    description: The principal, its workspaces, API keys and usage, and system status.
  - name: Runs
    description: >-
      Cloud runs (`--cloud`): renders, simulations, Recast log ingestion and
      transfers, their events and artifacts.
  - name: Models
    description: Customer fine-tunes and their workspace-owned model weights.
  - name: Datasets
    description: >-
      Datasets, their files as signed links (`simforge.dataset-files/v1`,
      `simforge datasets pull`), and copies out of shared datasets (SIMLOG-25k).
  - name: Maps and vehicles
    description: >-
      Maps the workspace can use, the vehicles a scenario can bind and the asset
      gallery.
  - name: Authoring
    description: >-
      Hosted scenario authoring: drafts, transactions, validation and map
      discovery.
  - name: Distribution
    description: >-
      The runtime and map pack agreement and signed downloads (`simforge runtime
      install`, `simforge maps pull`).
  - name: Telemetry
    description: Runtime usage telemetry, a condition of the runtime terms.
  - name: Benchmark
    description: Renderer benchmark results and scene packs (`simforge bench`).
  - name: Challenge
    description: >-
      The driving challenge: team, registry login and submissions (`simforge
      challenge`).
paths:
  /agent/identity:
    post:
      tags:
        - Sign-in
      summary: Register an AI agent
      description: >-
        auth.md Step 3. `service_auth`: an AI agent registers for the account
        `login_hint` names; show the person `claim.verification_uri` and
        `claim.user_code` (only that account, signed in with a verified email,
        can approve it), then poll the token endpoint with the claim grant.
        `identity_assertion`: an ID-JAG from a trusted agent provider
        (`issuer_not_enabled` while none is); it never creates or verifies an
        account. The first ID-JAG of a provider subject answers `401
        interaction_required` with a claim ceremony; once the person confirmed
        the link, an ID-JAG answers an identity assertion valid for at most an
        hour. `401 login_required` when `auth_time` is missing or over an hour
        old. Refusals carry `detail.reason`. `anonymous` answers
        `anonymous_not_enabled`. 10 registrations per address per minute; 30
        ID-JAGs per provider subject per 10 minutes.
      operationId: createAgentRegistration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AgentIdentityRequest'
      responses:
        '200':
          description: >-
            A `service_auth` registration and its first user code, or an
            identity assertion for a linked provider subject.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/AgentIdentityResponse'
                  - $ref: '#/components/schemas/AgentAssertionResponse'
        '400':
          description: 'The request failed: an OAuth error object.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CliOAuthError'
        '401':
          description: >-
            `interaction_required` (the person confirms the first link;
            `WWW-Authenticate: AgentAuth error="interaction_required"`), or
            `login_required` with `max_age` (an OAuth error object).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentInteractionRequired'
        '403':
          description: 'The request failed: an OAuth error object.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CliOAuthError'
        '429':
          description: 'The request failed: an OAuth error object.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CliOAuthError'
        '503':
          description: 'The request failed: an OAuth error object.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CliOAuthError'
      security: []
components:
  schemas:
    AgentIdentityRequest:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - service_auth
            login_hint:
              type: string
              minLength: 3
              maxLength: 320
              description: >-
                The email of the SimForge account the agent acts for. Only that
                account, signed in and with a verified email, can approve the
                registration.
            scope:
              type: string
              maxLength: 200
              description: >-
                Space-separated scopes the person is asked to approve. Omitted:
                every scope in the metadata's `scopes_supported`.
          required:
            - type
            - login_hint
          additionalProperties: false
        - type: object
          properties:
            type:
              type: string
              enum:
                - identity_assertion
            assertion_type:
              type: string
              enum:
                - urn:ietf:params:oauth:token-type:id-jag
            assertion:
              type: string
              minLength: 1
              maxLength: 8192
              description: >-
                An ID-JAG from a trusted agent provider: `aud` = this issuer, a
                fresh `jti`, `exp` within 10 minutes, `email` with
                `email_verified: true`, and `auth_time` within the last hour.
          required:
            - type
            - assertion_type
            - assertion
          additionalProperties: false
    AgentIdentityResponse:
      type: object
      properties:
        registration_id:
          type: string
        registration_type:
          type: string
          enum:
            - service_auth
            - identity_assertion
        claim_url:
          type: string
          description: >-
            Where to re-mint a user code for this registration (`POST`, with
            `claim_token` and the same `email`).
        claim_token:
          type: string
          description: >-
            Returned once: poll the token endpoint with it. Keep it in memory
            only.
        claim_token_expires:
          type: string
          description: When the registration closes (ISO 8601); after it, register again.
        post_claim_scopes:
          type: array
          items:
            type: string
        claim:
          type: object
          properties:
            user_code:
              type: string
              description: >-
                The code the person types on the verification page. Show it to
                the person, never send it anywhere.
            expires_in:
              type: integer
              description: Seconds until this user code expires.
            verification_uri:
              type: string
              description: >-
                The page the person opens: it asks them to sign in first, then
                for the code.
            interval:
              type: integer
              description: Seconds between token polls.
          required:
            - user_code
            - expires_in
            - verification_uri
            - interval
      required:
        - registration_id
        - registration_type
        - claim_url
        - claim_token
        - claim_token_expires
        - post_claim_scopes
        - claim
    AgentAssertionResponse:
      type: object
      properties:
        registration_id:
          type: string
        registration_type:
          type: string
          enum:
            - identity_assertion
        identity_assertion:
          type: string
          description: >-
            Exchange it with the JWT-bearer grant for an access token until
            `assertion_expires` (at most an hour).
        assertion_expires:
          type: string
        scopes:
          type: array
          items:
            type: string
      required:
        - registration_id
        - registration_type
        - identity_assertion
        - assertion_expires
        - scopes
    CliOAuthError:
      type: object
      properties:
        error:
          type: string
          description: >-
            Machine code: an RFC 6749/8628 error (`invalid_grant`,
            `authorization_pending`, `slow_down`, `invalid_token`,
            `insufficient_scope`) or a SimForge code (`not_found`,
            `rate_limited`, …).
        error_description:
          type: string
          description: One sentence for a person.
        detail:
          type: object
          additionalProperties: {}
      required:
        - error
        - error_description
    AgentInteractionRequired:
      type: object
      properties:
        registration_id:
          type: string
        registration_type:
          type: string
          enum:
            - service_auth
            - identity_assertion
        claim_url:
          type: string
          description: >-
            Where to re-mint a user code for this registration (`POST`, with
            `claim_token` and the same `email`).
        claim_token:
          type: string
          description: >-
            Returned once: poll the token endpoint with it. Keep it in memory
            only.
        claim_token_expires:
          type: string
          description: When the registration closes (ISO 8601); after it, register again.
        post_claim_scopes:
          type: array
          items:
            type: string
        claim:
          type: object
          properties:
            user_code:
              type: string
              description: >-
                The code the person types on the verification page. Show it to
                the person, never send it anywhere.
            expires_in:
              type: integer
              description: Seconds until this user code expires.
            verification_uri:
              type: string
              description: >-
                The page the person opens: it asks them to sign in first, then
                for the code.
            interval:
              type: integer
              description: Seconds between token polls.
          required:
            - user_code
            - expires_in
            - verification_uri
            - interval
        error:
          type: string
          enum:
            - interaction_required
        error_description:
          type: string
      required:
        - registration_id
        - registration_type
        - claim_url
        - claim_token
        - claim_token_expires
        - post_claim_scopes
        - claim
        - error
        - error_description

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.