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

# Restore a commit

> Resets the sandbox's files to a commit. Production doesn't change. To publish the restored source, create a deployment.



## OpenAPI

````yaml /api-reference/openapi.json post /api/apps/{id}/restore
openapi: 3.1.0
info:
  title: Judt API
  version: 1.0.0
  description: >-
    The Judt API creates and runs Apps. Each App has a sandbox, where you and
    agents edit and run its source, and a production deployment that serves it.


    ## Authentication


    Send an API token or an OAuth access token in the `Authorization` header.


    - **API token:** send it as a bearer token. A token belongs to one
    organization, and you create and revoke tokens in the dashboard. A token
    scoped to one App can reach only that App. An organization-wide token can
    also create a short-lived token for one App with `POST /api/tokens`, to give
    to an agent or an MCP client.

    - **OAuth access token:** an agent gets one when a person approves its
    access to one organization, so the person never handles a token. Reads need
    the `apps:read` scope, and changes need `apps:write`. To register and sign
    in, follow https://judt.ai/auth.md. Send the token as a bearer token, or
    with a DPoP proof if it's bound to a DPoP key. One access token can work on
    both this API and the MCP server at https://api.judt.ai/mcp.


    ## Sandboxes


    Creating an App reserves its address, but it doesn't start a sandbox or
    publish anything. There's no endpoint to start a sandbox. A request that
    needs the sandbox starts it first, so the first request after the sandbox
    goes idle takes longer. Files, Git, commands, commits, restores, previews,
    and deployments all need the sandbox.


    The sandbox stops on its own when it's idle. If `sandbox_status` is
    `failed`, the most recent start failed, and the API retries it while the
    sandbox is needed.


    ## Pagination


    A list returns one page at a time, in the form `{"results": [...],
    "has_more": true, "next_cursor": "CURSOR"}`. To get the next page, list
    again with `cursor` set to `next_cursor`, and the same `sort` and filters.
    Results that arrive while you page don't shift your pages. On the last page,
    `has_more` is `false`, and `next_cursor` still finds results added later.


    ## Retries


    A request that creates, changes, or deletes something returns `200` after
    the work is done, with the resource as it is afterward. To retry a request
    safely, send an `Idempotency-Key` header. For 30 days, a retry with the same
    key and input returns the first request's result instead of repeating the
    work. If you don't send a key, the API generates one and returns it in the
    `Idempotency-Key` response header. Setting and deleting a Secret take no
    key, because repeating them changes nothing. A visitor token or a preview
    link is created fresh each time, because nothing is stored to repeat.


    The API records file writes and deletes, commands, commits, and restores
    before it runs them. The response status tells you what to do next:


    - `503` or `504`: the action is recorded but not finished. To get its
    result, retry with the same key. A new key would run the action again.

    - `4xx` or `502`: the result is final. A retry with the same key returns the
    same response.


    A `504 request_timeout` response says how far the work got and which event
    to check. The work continues, and a retry with the same key picks it up.


    ## Troubleshooting


    To see what happened to an App's sandbox, deployments, and deletion, list
    its events with `GET /api/apps/{id}/events`. To see what the App's code did,
    including requests, output, exceptions, and failed builds, list its logs
    with `GET /api/apps/{id}/logs`.


    ## Time limits


    Requests have the following time limits:


    - Stopping the sandbox: 120 seconds.

    - File writes, commits, and restores: 120 seconds.

    - Commands: the command's `timeout_seconds`, up to 120 seconds, plus 60
    seconds to stop it and save its result.

    - Publishing, unpublishing, deleting an App, and changing production
    settings: 540 seconds, including any sandbox start.


    If a file write, commit, restore, or command has to start the sandbox, it
    gets up to 120 more seconds.


    ## Errors


    An error returns a JSON body in the form `{"error": {"code": "CODE",
    "message": "MESSAGE", "detail": "DETAIL", "request_id": "REQUEST_ID"}}`. The
    `code` value is stable, so check it rather than `message`. The `detail`
    value is optional. When a parameter or a body field isn't valid, the request
    returns `400 invalid_request`, `message` names the field, and `detail` lists
    every problem if there's more than one.


    When the server rejects a credential, it returns a JSON error body and sets
    the `WWW-Authenticate` header. A `401` response includes the
    `resource_metadata` URL in `WWW-Authenticate` (RFC 9728):


    | Status | Error code / header | Cause | Action |

    |---|---|---|---|

    | `401` | `unauthenticated` | The request has no credential, or the API
    token or OAuth access token is invalid, expired, or revoked. | Send a valid
    API token or OAuth access token. |

    | `401` | `invalid_token` | `WWW-Authenticate` error when an API token or
    OAuth access token is expired, revoked, or issued for a different `resource`
    audience. | Refresh the access token, or request a token for the target
    server. |

    | `401` | `invalid_dpop_proof` | The `DPoP` proof header is missing,
    expired, replayed, or signed for a different HTTP method or URL. | Create a
    new DPoP proof for the request method and URL. |

    | `403` | `insufficient_scope` | The OAuth token does not have the required
    scope (`apps:read` or `apps:write`). | Request authorization with the scope
    named in `WWW-Authenticate`. |

    | `403` | `app_scoped_token` | An App-scoped API token called `POST
    /api/apps` or `POST /api/tokens`. | Use an organization-wide API token. |

    | `403` | `api_token_required` | An OAuth access token called `POST
    /api/tokens`. | Use an organization-wide API token. |

    | `403` | `sign_in_required` | A Personal Agent Session Token was used
    before the user signed in or after the user signed out. | Tell the user to
    sign in to the Session. |

    | `403` | `forbidden` | Your organization role (`member`) does not allow
    this action. | Ask an organization `owner` or `admin` to do the action. |
servers:
  - url: https://api.judt.ai
security: []
tags:
  - name: Account
    description: >-
      See who a credential acts for: the person, the organization, and what the
      credential can reach.
  - name: Apps
    description: Create, update, and delete Apps, and control who can reach them.
  - name: Tokens
    description: >-
      Create short-lived API tokens that reach one App, to give to an agent or
      an MCP client.
  - name: Secrets
    description: >-
      Store values, such as API keys, that an App reads at runtime. Responses
      never include Secret values.
  - name: Files
    description: Read and write the source files in an App's sandbox.
  - name: Sandbox
    description: >-
      Run commands, use Git, commit and restore source, and preview the App's
      sandbox.
  - name: Deployments
    description: Publish an App's source to production, and take it offline.
  - name: Monitoring
    description: See what happened to an App, and what its code did.
  - name: Templates
    description: The starting points for new Apps.
  - name: Agents
    description: >-
      Work with the in-product coding agent: sessions, turns, events, and the
      models it runs on. The agent itself works only through this API.
  - name: Feedback
    description: Tell the Judt team about bugs, friction, and anything else.
paths:
  /api/apps/{id}/restore:
    post:
      tags:
        - Sandbox
      summary: Restore a commit
      description: >-
        Resets the sandbox's files to a commit. Production doesn't change. To
        publish the restored source, create a deployment.
      operationId: restore_commit
      parameters:
        - name: id
          in: path
          required: true
          description: A unique ID that starts with `app_`.
          schema:
            type: string
            pattern: ^app_[0-9A-Za-z]{24}$
            example: app_Zj7XhMgplmTJcp5Dk4vcYuk0
        - name: Idempotency-Key
          in: header
          required: false
          description: >-
            A key that identifies this request for retries, up to 200 printable
            characters. A retry with the same key and input returns the first
            request's result instead of repeating the work. If you omit the key,
            the API generates one and returns it in the `Idempotency-Key`
            response header.
          schema:
            type: string
            minLength: 1
            maxLength: 200
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $schema: https://json-schema.org/draft/2020-12/schema
              type: object
              properties:
                commit_id:
                  type: string
                  pattern: ^cmt_[0-9A-Za-z]{24}$
                  description: >-
                    The ID of the commit to restore, from `GET
                    /api/apps/{id}/commits`.
              required:
                - commit_id
              additionalProperties: false
      responses:
        '200':
          description: The App.
          headers:
            Idempotency-Key:
              schema:
                type: string
              description: >-
                The key this request ran under: the one you sent, or one the API
                generated. To pick up the work after a timeout, retry with this
                key.
            Idempotency-Retry-Window:
              schema:
                type: string
                example: '2592000'
              description: >-
                How long you can retry with the same key, in seconds: 2592000
                (30 days).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/App'
        '400':
          $ref: '#/components/responses/Error'
        '401':
          $ref: '#/components/responses/Error'
        '403':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '409':
          description: |-
            - `idempotency_conflict`: the key was used with a different request.
            - `idempotency_expired`: the key is too old to reuse.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '410':
          $ref: '#/components/responses/Error'
        '413':
          $ref: '#/components/responses/Error'
        '422':
          description: >-
            - `commit_not_found`: the commit is no longer in the App's
            repository.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/Error'
        '502':
          description: >-
            The sandbox failed the action, for example with
            `process_isolation_unavailable`, or it returned a response that the
            API can't use (`sandbox_incompatible`). This result is final. A
            retry with the same `Idempotency-Key` returns the same error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: >-
            The action is recorded but not finished, and `code` and `message`
            say what's holding it back. The action hasn't run yet, its outcome
            isn't known yet, or it's applied but not yet backed up
            (`recovery_degraded`). To get its result, retry with the same
            `Idempotency-Key`. A new key would run the action again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '504':
          $ref: '#/components/responses/Error'
      security:
        - ApiToken: []
        - OAuth:
            - apps:write
        - DPoP:
            - apps:write
components:
  schemas:
    App:
      $schema: https://json-schema.org/draft/2020-12/schema
      type: object
      properties:
        id:
          type: string
          description: The App's ID, which starts with `app_`.
        name:
          type: string
          description: The App's display name.
        slug:
          type: string
          description: >-
            The App's label under the App base domain. The App keeps serving at
            this address after you add a custom domain.
        domain:
          description: The App's custom domain, or null if it doesn't have one.
          type:
            - string
            - 'null'
        url:
          type: string
          format: uri
          description: >-
            The App's public URL: its custom domain if it has one, or else its
            slug address.
        template:
          type: object
          properties:
            id:
              type: string
              description: The template's ID.
            version:
              type: integer
              exclusiveMinimum: 0
              description: The template's version.
              example: 3
          required:
            - id
            - version
          additionalProperties: false
          description: >-
            The template that the App was created from. Until the sandbox first
            starts, `version` is the template's version when the App was
            created. After that, it's the version that the sandbox was set up
            from.
        sandbox_status:
          type: string
          enum:
            - stopped
            - starting
            - running
            - stopping
            - failed
          description: >-
            The sandbox's state. Any request that needs the sandbox starts it,
            and the sandbox stops on its own when it's idle.

            - `stopped`: the sandbox isn't running.

            - `starting`: the sandbox is starting.

            - `running`: the sandbox is running.

            - `stopping`: the sandbox is committing changes and stopping.

            - `failed`: the most recent start failed. The API retries while the
            sandbox is needed, and any request that needs the sandbox retries
            right away.
        sandbox_error:
          anyOf:
            - type: object
              properties:
                code:
                  type: string
                  description: A stable code for the error.
                message:
                  type: string
                  description: A readable explanation of the error.
                at:
                  type: string
                  format: date-time
                  description: When the attempt failed.
                  example: '2026-10-03T14:01:30.000Z'
                retry_at:
                  anyOf:
                    - type: string
                      format: date-time
                      example: '2026-10-03T14:01:30.000Z'
                    - type: 'null'
                  description: >-
                    When the API tries again on its own, or null if it won't. If
                    it's null, the next request that needs the sandbox tries
                    again.
              required:
                - code
                - message
                - at
                - retry_at
              additionalProperties: false
            - type: 'null'
          description: >-
            The most recent failed attempt to start or stop the sandbox, or
            null. It's cleared after an attempt succeeds.
        production:
          type: object
          properties:
            visibility:
              type: string
              enum:
                - public
                - password
                - private
              description: >-
                Who can reach the published App:

                - `public`: anyone.

                - `password`: anyone with the App's password, for 60 minutes at
                a time.

                - `private`: members of the App's organization, who sign in
                through judt.


                Access tokens open password-protected and private Apps. The
                sandbox is always private to the organization.
            password_updated_at:
              anyOf:
                - type: string
                  format: date-time
                  example: '2026-10-03T14:01:30.000Z'
                - type: 'null'
              description: >-
                When the App's password was last set, or null if `visibility`
                isn't `password`.
            status:
              type: string
              enum:
                - unpublished
                - starting
                - ready
                - idle
                - stopped
                - unhealthy
                - failed
                - unknown
              description: >-
                The state of the published App:

                - `unpublished`: nothing is published, either before the first
                deployment or after you unpublish the App. The next deployment
                publishes it.

                - `starting`: the published version is starting.

                - `ready`: the App is serving requests.

                - `idle`: the App is asleep between requests. The next request
                wakes it.

                - `stopped`: the App isn't serving until something changes.
                `error` says why.

                - `unhealthy`: the App is running but isn't healthy. `error`
                says why.

                - `failed`: the App failed. `error` says why.

                - `unknown`: the runtime hasn't reported the App's state
                recently.
            deployment_id:
              description: >-
                The ID of the deployment that's serving, or null if nothing is
                published.
              type:
                - string
                - 'null'
            error:
              anyOf:
                - type: object
                  properties:
                    code:
                      type: string
                      description: A stable code for the error.
                    message:
                      type: string
                      description: A readable explanation of the error.
                  required:
                    - code
                    - message
                  additionalProperties: false
                - type: 'null'
              description: Why the App stopped, failed, or is unhealthy, or null otherwise.
            observed_at:
              anyOf:
                - type: string
                  format: date-time
                  example: '2026-10-03T14:01:30.000Z'
                - type: 'null'
              description: >-
                When the runtime last reported the App's state, or null if
                there's no recent report.
          required:
            - visibility
            - password_updated_at
            - status
            - deployment_id
            - error
            - observed_at
          additionalProperties: false
          description: The published App and who can reach it.
        deleted_at:
          anyOf:
            - type: string
              format: date-time
              example: '2026-10-03T14:01:30.000Z'
            - type: 'null'
          description: >-
            When the App was deleted, or null if it isn't deleted. A deleted App
            stays readable for 30 days.
        created_at:
          type: string
          format: date-time
          description: When the App was created.
          example: '2026-10-03T14:01:30.000Z'
        updated_at:
          type: string
          format: date-time
          description: When the App was last changed.
          example: '2026-10-03T14:01:30.000Z'
      required:
        - id
        - name
        - slug
        - domain
        - url
        - template
        - sandbox_status
        - sandbox_error
        - production
        - deleted_at
        - created_at
        - updated_at
      additionalProperties: false
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: A stable code for the error, such as `not_found`.
            message:
              type: string
              description: A readable explanation of the error.
            detail:
              type: string
              description: >-
                More information, if any: the sandbox's error, a provider
                message, or, for a `504`, how far the work got and the ID of its
                latest event.
            request_id:
              type: string
              description: The request's ID. Include it when you contact support.
  responses:
    Error:
      description: An error, with its code and the request ID.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiToken:
      type: http
      scheme: bearer
      description: >-
        An API token for one organization. You create and revoke tokens in the
        dashboard. A token scoped to one App can reach only that App, so give
        that kind of token to an agent. An organization-wide token can create a
        short-lived one with `POST /api/tokens`.
    OAuth:
      type: oauth2
      description: >-
        An OAuth access token for one person and organization, sent as a bearer
        token. https://judt.ai/auth.md describes the ways an agent can get one.
        Request the resource https://api.judt.ai, and also
        https://api.judt.ai/mcp to use the same token on the MCP server. The
        person's role still applies.
      flows:
        authorizationCode:
          authorizationUrl: https://judt.ai/api/auth/oauth2/authorize
          tokenUrl: https://judt.ai/api/auth/oauth2/token
          refreshUrl: https://judt.ai/api/auth/oauth2/token
          scopes:
            apps:read: >-
              See the organization's Apps, with their files, deployments, and
              logs.
            apps:write: >-
              Change the organization's Apps: edit files, run commands, deploy,
              and manage Secrets.
    DPoP:
      type: http
      scheme: DPoP
      description: >-
        An OAuth access token bound to a DPoP key (RFC 9449), sent with a DPoP
        proof. A token request with a DPoP proof gets one, and a Personal Agent
        Protocol Session Token is one: a Personal Agent starts at
        https://judt.ai/.well-known/poppy.json. Scopes are the same as for
        OAuth.

````

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