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

# Clean up an evaluation sandbox

> Idempotently stops target work, revokes target grants, releases the
sandbox pin, and deletes the ephemeral project. Cleanup state is retained
as evidence; a cleanup error never hides the run's primary failure.




## OpenAPI

````yaml /openapi/davinci-public.v2.yaml delete /api/v2/evaluation-runs/{runId}
openapi: 3.1.0
info:
  title: Davinci Public API
  version: 2.0.0
  description: >
    Public Routing Server API contract for Davinci integrations and official
    SDKs.


    Most operations live on the canonical `/api/v2/projects` mount and accept a

    personal access token (`dav_ak_live_…` / `dav_ak_test_…`) or browser access

    token. Evaluation-run creation is the deliberate exception: it accepts only
    a

    `purpose=automation` grant issued to a running Code execution.

    Project membership and role are checked on every user call, and an API key
    is

    additionally bounded by the permission ceiling derived from its scopes — a
    key

    can never exceed what its owner can do, and usually does less.


    Collaboration operations (invitations, membership changes, ownership
    transfer)

    are deliberately absent: they require a browser session and are not part of
    the

    programmatic surface.


    ## Two planes


    Most operations are **control plane**: they run on the Routing Server, take

    small requests, and answer quickly. A few are **data plane**, marked

    `x-plane: data`, and go straight to the machine holding your project — the
    only

    practical way to move multi-gigabyte files or hold a connection open for
    half

    an hour.


    Data-plane operations use a different host and a different credential.
    Create a

    session on a project and it returns both: a `dataPlane.url` to send to and a

    short-lived `dataPlane.token` (`dav_gr_…`, a *grant*) to send with. A grant

    reaches exactly one project, carries no more permission than the key that

    minted it, expires in minutes, and dies when its session closes. It is not

    interchangeable with an API key in either direction.


    The data-plane host never names a specific machine, so a project that moves

    between machines mid-session stays reachable at the same URL.
servers:
  - url: https://davinci-app.com
    description: Production (control plane)
  - url: https://davinci-app.com/data
    description: >-
      Production (data plane). Serves the operations marked `x-plane: data`,
      using a session's grant rather than an API key.
security:
  - ApiKeyBearer: []
tags:
  - name: Projects
    description: >-
      Create, inspect, open, close, and delete projects, and manage their
      attached files.
  - name: Content
    description: >
      Read and write the objects a project is made of. These reach the running

      project rather than storage, so they see uncommitted work — and so they
      open

      the project if it is not already open.
  - name: Branches
    description: >
      Branches, commits, and the history of a single object. A commit captures
      the

      running project's state, so these operations need the branch loaded, which
      they

      arrange for the caller.
  - name: Sessions
    description: >
      A session opens a project, holds it open, and issues the grant that
      reaches the

      data plane. It is the programmatic equivalent of having a project open in
      a

      browser tab: while it lives, the project stays loaded.


      It is also where the agent lives. Send it a prompt, read its status from
      the

      session, read the transcript back, and stop a run that is going the wrong
      way.
  - name: AgentModels
    description: >
      Chat models available to your account. The returned keys are the values
      accepted

      by the session message API; availability follows your subscription,
      tenant, and

      any profile assigned to your account.
  - name: Tools
    description: >
      Invoke one of the agent's tools yourself, without the agent. Useful when
      you

      already know the operation you want and do not need a model to choose it —
      and

      when you want a deterministic result rather than an interpreted one.


      A tool is still held to the permissions of the credential invoking it, so
      a

      key cannot reach through a tool to something its scopes exclude.
  - name: Files
    description: >
      Data-plane file transfer. These reach your project's machine directly
      using a

      session's grant, which is what allows request bodies far larger than the

      control plane accepts.
  - name: Usage
    description: >
      What your models cost, broken down by model, project, session, or day.
      These

      read the usage ledger, which records one event per completed provider call
      —

      not your credit balance, which is `/api/v2/billing`.


      Usage is reported on an interval rather than per call, so a run that is
      still

      going may not be fully counted yet. Every response carries `asOf`, the
      moment

      the newest counted event was recorded, so you can see how current a total
      is

      instead of guessing.


      This is separate from `projects:read` on purpose: a key that reads your

      project data is not thereby allowed to see what you spend.
  - name: Evaluations
    description: |
      Lifecycle for the ephemeral target sandbox an evaluation runs against.
      Creation is available only to a `purpose=automation` grant issued to a
      running Code execution, so a sandbox always belongs to code rather than to
      a person's key. It returns a second, `purpose=evaluation` grant bound to
      the new sandbox; it never upgrades or replaces the source credential.
  - name: Tests
    description: >
      Asynchronously run an authored Test. The Test executes its linked Code

      object and applies its native evaluation criteria to derive the verdict.

      This is one way to start Code, not a prerequisite for anything the Code
      can

      do: the same function called directly holds the same authority.
  - name: Organizations
    description: Discover organizations available as containers for team planning.
  - name: Cards
    description: >
      Project-scoped agile cards, their index hierarchy, comments, tags,
      assignees,

      card dependencies, and design-object references. Project access is checked

      on every call; an inaccessible project is reported as not found.
  - name: Teams
    description: >
      Organization-scoped team boards, linked projects, workflow columns,
      sprints,

      analytics, and card placements. Team visibility is privacy preserving:

      inaccessible organizations, private teams, and cross-organization ids are

      reported as not found rather than revealing that they exist.
paths:
  /api/v2/evaluation-runs/{runId}:
    parameters:
      - $ref: '#/components/parameters/RunId'
    delete:
      tags:
        - Evaluations
      summary: Clean up an evaluation sandbox
      description: >
        Idempotently stops target work, revokes target grants, releases the

        sandbox pin, and deletes the ephemeral project. Cleanup state is
        retained

        as evidence; a cleanup error never hides the run's primary failure.
      operationId: deleteEvaluationRun
      responses:
        '200':
          description: Cleanup completed or had already completed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvaluationRun'
        '202':
          description: Cleanup has been requested and is still running.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvaluationRun'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - ExecutionGrantBearer: []
        - ApiKeyBearer: []
components:
  parameters:
    RunId:
      name: runId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Evaluation-run or Test-run id returned by its create operation.
  schemas:
    EvaluationRun:
      type: object
      required:
        - runId
        - sourceProjectId
        - status
        - sandbox
        - createdAt
        - expiresAt
        - cleanup
      properties:
        runId:
          type: string
          format: uuid
        sourceProjectId:
          type: string
        testId:
          type:
            - string
            - 'null'
          description: |
            The Test whose Results Value started the Code, when a Test did.
            Absent for a Code object run directly.
        testRunId:
          type:
            - string
            - 'null'
          format: uuid
          description: The Test run that started the Code, when one did.
        codeExecutionId:
          type: string
        sessionId:
          type: string
          format: uuid
          description: Headless target session attached to the evaluation data-plane grant.
        status:
          $ref: '#/components/schemas/EvaluationRunStatus'
        sandbox:
          $ref: '#/components/schemas/EvaluationSandbox'
        dataPlane:
          $ref: '#/components/schemas/EvaluationDataPlaneAccess'
        evidence:
          $ref: '#/components/schemas/EvaluationEvidence'
        quality:
          $ref: '#/components/schemas/QualityObservation'
        failure:
          $ref: '#/components/schemas/RunFailure'
        cleanup:
          $ref: '#/components/schemas/EvaluationCleanup'
        createdAt:
          type: string
          format: date-time
        expiresAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      additionalProperties: true
    EvaluationRunStatus:
      type: string
      enum:
        - provisioning
        - ready
        - running
        - cleaning
        - cleaned
        - failed
        - expired
      description: |
        `ready` means the target is pinned and its grant can be used. `failed`
        is an infrastructure failure, not a low quality score. `cleaned` and
        `expired` are terminal and carry no usable grant.
    EvaluationSandbox:
      type: object
      required:
        - projectId
        - branchName
        - ephemeral
      properties:
        projectId:
          type: string
          description: >-
            Server-chosen target project. It is never accepted from the create
            body.
        branchName:
          type: string
        name:
          type: string
        ephemeral:
          type: boolean
          description: Always true for an evaluation-created target.
        deleteAfter:
          type: string
          format: date-time
      additionalProperties: true
    EvaluationDataPlaneAccess:
      allOf:
        - $ref: '#/components/schemas/DataPlaneAccess'
        - type: object
          required:
            - purpose
          properties:
            purpose:
              type: string
              const: evaluation
              description: |
                Target-bound evaluation authority. Ordinary data-plane/execution
                grants remain denied from agent and git routes; this purpose
                admits only the target agent, and still denies git.
          additionalProperties: true
    EvaluationEvidence:
      type: object
      required:
        - capturedAt
        - transcript
        - tree
        - usage
      properties:
        capturedAt:
          type: string
          format: date-time
        transcript:
          $ref: '#/components/schemas/AgentTranscript'
        tree:
          $ref: '#/components/schemas/ProjectTree'
        usage:
          $ref: '#/components/schemas/UsageResponse'
        seededObjectIds:
          type: array
          items:
            type: string
        artifacts:
          type: array
          items:
            type: object
            required:
              - name
            properties:
              name:
                type: string
              mediaType:
                type: string
              fileId:
                type: string
              sha256:
                type: string
                pattern: ^[0-9a-f]{64}$
            additionalProperties: true
        summary:
          type: object
          additionalProperties: true
      additionalProperties: true
    QualityObservation:
      type: object
      required:
        - value
      properties:
        value:
          type: number
          description: >-
            Finite numeric observation returned to native Test evaluation
            criteria.
        unit:
          type: string
        rubric:
          type: string
        metrics:
          type: object
          additionalProperties:
            type: number
      additionalProperties: false
    RunFailure:
      type: object
      required:
        - code
        - message
        - infrastructure
      properties:
        code:
          type: string
          enum:
            - EVALUATION_SCOPE_MISSING
            - EVALUATION_AGENT_FAILED
            - EVALUATION_TIMEOUT
            - EVALUATION_EVIDENCE_MISSING
            - EVALUATION_OBSERVATION_INVALID
            - EVALUATION_CLEANUP_FAILED
            - CODE_EXECUTION_FAILED
            - TEST_CANCELLED
            - TEST_RUN_FAILED
            - TEST_RUN_TIMED_OUT
        message:
          type: string
        infrastructure:
          type: boolean
          description: True when no quality verdict may be inferred from this failure.
        details:
          type: object
          additionalProperties: true
      additionalProperties: true
    EvaluationCleanup:
      type: object
      required:
        - status
        - requested
      properties:
        status:
          type: string
          enum:
            - not_started
            - pending
            - completed
            - failed
        requested:
          type: boolean
        requestedAt:
          type: string
          format: date-time
        completedAt:
          type: string
          format: date-time
        grantsRevoked:
          type: integer
          minimum: 0
        projectDeleted:
          type: boolean
        failure:
          $ref: '#/components/schemas/RunFailure'
      additionalProperties: true
    ErrorEnvelope:
      description: >
        The error shape for every failure on this API, whether it was refused by
        the

        credential layer before reaching a domain or by the domain itself.


        Branch on `code`, which is stable. `message` is for a person reading a
        log or

        a dialog and may be reworded. `details` carries fields specific to one

        failure — a project-limit refusal reports its numbers there — and is
        absent

        when there are none.
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
              additionalProperties: true
          additionalProperties: true
      additionalProperties: true
    DataPlaneAccess:
      type: object
      description: >
        Everything needed to address the data plane: where to send, what to send
        with,

        and the path parameters that are not obvious from the project id alone.
      required:
        - url
        - token
        - expiresAt
        - connectionId
        - ownerId
        - userId
        - projectKey
        - operations
      properties:
        url:
          type: string
          format: uri
          description: >
            Base URL for data-plane operations. Names no specific machine, so it
            stays

            valid if the project moves.
        token:
          type: string
          description: >
            The grant, `dav_gr_…`. Returned only here and only once — it is not
            stored

            in recoverable form, so a lost grant is replaced by refreshing the
            session

            rather than looked up.
        expiresAt:
          type: string
          format: date-time
        connectionId:
          type: string
          description: Pass as the `connectionId` path parameter on upload.
        ownerId:
          type: string
          description: Pass as the `ownerId` path parameter.
        userId:
          type: string
          description: Pass as the `userId` path parameter on upload.
        projectKey:
          type: string
          description: >
            Pass as the `projectId` path parameter. Compound form

            `{projectId}--{branchName}`, since the data plane addresses a
            branch.
        operations:
          type: array
          items:
            type: string
          description: Data-plane operations this grant authorizes.
      additionalProperties: true
    AgentTranscript:
      type: object
      required:
        - sessionId
        - taskId
        - source
        - status
        - entryCount
        - messages
      properties:
        sessionId:
          type: string
          format: uuid
        taskId:
          type: string
        source:
          type: string
          enum:
            - live
            - persisted
            - none
          description: >
            Where the answer came from. `live` is current; `persisted` is the
            copy saved

            when a run ended, and so lags a run in progress.
        status:
          $ref: '#/components/schemas/AgentStatus'
        entryCount:
          type: integer
          minimum: 0
          description: Entries in the whole conversation, not just the returned window.
        messages:
          type: array
          items:
            $ref: '#/components/schemas/AgentMessage'
          description: Oldest first. Bounded by `limit`, taken from the end.
      additionalProperties: true
    ProjectTree:
      type: object
      description: |
        Flat list of project objects excluding the project object itself. New
        projects contain reserved `Model` and `Library` packages whose `parent`
        is the project id; callers must not assume a parentless node exists.
      required:
        - objectCount
        - tree
      properties:
        objectCount:
          type: integer
          minimum: 0
          description: Total objects in the project, including the project object itself.
        tree:
          type: array
          items:
            $ref: '#/components/schemas/TreeNode'
      additionalProperties: true
    UsageResponse:
      type: object
      required:
        - scope
        - asOf
        - totals
      properties:
        scope:
          type: string
          enum:
            - account
            - project
            - session
          description: What the numbers cover, determined by the path you called.
        projectId:
          type: string
          description: Present on the project and session reads. Always the bare id.
        sessionId:
          type: string
          format: uuid
          description: Present on the session read.
        asOf:
          type:
            - string
            - 'null'
          format: date-time
          description: >
            When the newest counted event was recorded, or null when the scope
            holds

            none. This is the honest bound on freshness: the engine reports
            usage on an

            interval, so a run's last few seconds may not be included. Null
            means

            "nothing here", not "nothing yet" — a scope with no usage looks the
            same

            either way, and inventing a timestamp would hide that.
        totals:
          $ref: '#/components/schemas/UsageTotals'
        groupBy:
          type: string
          enum:
            - model
            - project
            - session
            - day
          description: Echoed back when you asked for a breakdown.
        groups:
          type: array
          description: |
            One entry per group, largest spend first — except `day`, which is
            chronological. Absent unless you passed `groupBy`.
          items:
            $ref: '#/components/schemas/UsageGroup'
      additionalProperties: true
    AgentStatus:
      type: string
      description: >
        - `no_session` — the machine has no record of this session; it lapsed or
        the
          project restarted. Create a new one.
        - `project_not_running` — the session is known but its project has
        unloaded.

        - `idle` — the session is live and no run has been started.

        - `starting` — a run is being set up.

        - `running` — a run is in progress.

        - `paused` — a run was stopped and can be continued with a new prompt.

        - `completed` — the run finished.

        - `failed` — the run ended in an error. The transcript says why.

        - `unknown` — the machine could not be reached for this field. Retry;
        anything
          else in the same response is still valid.

        `paused`, `completed`, and `failed` are terminal for a run.
      enum:
        - no_session
        - project_not_running
        - idle
        - starting
        - running
        - paused
        - completed
        - failed
        - unknown
    AgentMessage:
      type: object
      required:
        - index
        - role
        - kind
      properties:
        index:
          type: integer
          minimum: 0
          description: Position in the whole conversation, so a window can be placed.
        role:
          type: string
          enum:
            - user
            - agent
        kind:
          type: string
          description: >
            `text` for what was said, `thought` for the agent's reasoning,
            `tool` for a

            tool it used, `error` for a failure it hit. Treat an unrecognized
            value as

            informational rather than as a problem — new kinds can appear.
        text:
          type: string
          description: The content. For a `tool` entry, the tool's name.
        timestamp:
          type:
            - integer
            - 'null'
          description: Milliseconds since the epoch.
        messageId:
          type: string
          description: Present on your own prompts, matching what you sent.
        tool:
          $ref: '#/components/schemas/AgentToolUse'
      additionalProperties: true
    TreeNode:
      type: object
      description: >
        One object, as a node. Parentage is expressed by `parent` and
        `childrenCount`

        rather than by nesting, so the array is flat and a node can be read
        without

        walking to it.
      required:
        - id
        - name
        - type
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: string
        parent:
          type:
            - string
            - 'null'
        childrenCount:
          type: integer
          minimum: 0
      additionalProperties: true
    UsageTotals:
      type: object
      required:
        - credits
        - promptTokens
        - completionTokens
        - reasoningTokens
        - cacheWriteTokens
        - cacheReadTokens
        - eventCount
      properties:
        credits:
          type: number
          description: Credits charged, to six decimal places.
        promptTokens:
          type: integer
        completionTokens:
          type: integer
        reasoningTokens:
          type: integer
          description: Thinking tokens, charged at the completion rate.
        cacheWriteTokens:
          type: integer
        cacheReadTokens:
          type: integer
        eventCount:
          type: integer
          description: >
            Charged calls counted. Not all of them are token-priced — image
            generation

            and web search are charged per call, so a non-zero `credits` with
            zero

            tokens is normal rather than a gap.
      additionalProperties: true
    UsageGroup:
      allOf:
        - $ref: '#/components/schemas/UsageTotals'
        - type: object
          description: >
            Totals for one group. Which identifying field is present depends on

            `groupBy`, and any of them may be null — usage with no project, for
            example

            naming a new project, is real usage that belongs to no project.
          properties:
            provider:
              type:
                - string
                - 'null'
              description: Present when grouping by model.
            model:
              type:
                - string
                - 'null'
              description: Present when grouping by model.
            projectId:
              type:
                - string
                - 'null'
              description: Present when grouping by project.
            sessionId:
              type:
                - string
                - 'null'
              description: Present when grouping by session.
            day:
              type:
                - string
                - 'null'
              format: date-time
              description: Midnight UTC of the day. Present when grouping by day.
          additionalProperties: true
    AgentToolUse:
      type: object
      description: Present only on entries whose `kind` is `tool`.
      properties:
        name:
          type:
            - string
            - 'null'
        status:
          type:
            - string
            - 'null'
          description: >
            `working` while it runs, `complete` when it succeeded, otherwise the
            severity

            of what went wrong.
        params:
          description: The arguments the agent chose. Null when the tool takes none.
        result:
          description: What the tool returned. Shape is the tool's own.
        error:
          type: string
          description: Present when the tool failed.
      additionalProperties: true
  responses:
    Unauthorized:
      description: >
        No credential was supplied, or the supplied credential is malformed,
        expired,

        or revoked. A credential that is present but unusable is never
        downgraded to

        an anonymous request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: >
        Authenticated but not authorized. Either the acting user lacks the
        required

        resource permission, the key's scope ceiling excludes it, or the
        endpoint

        rejects this credential type (`CREDENTIAL_NOT_PERMITTED`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: >
        The resource does not exist in the parent named by the path, or is
        hidden

        from the caller. Absence and privacy denial are deliberately

        indistinguishable so project, organization, and private-team existence

        cannot be probed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    RateLimited:
      description: Request rate exceeded, either globally or for this key.
      headers:
        Retry-After:
          schema:
            type: integer
            minimum: 1
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    ApiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: dav_ak_live_... or dav_ak_test_...
      x-default: dav_ak_live_your_token
      description: >
        Personal access token. The scopes granted at issuance determine both
        which

        operations the key may call and the ceiling on the resource permissions
        it

        can exercise. Each scope family is a ladder: `projects:manage` implies

        `projects:write` and `projects:read`; `cards:manage` implies
        `cards:write`

        and `cards:read`; and `teams:manage` implies `teams:write` and
        `teams:read`.

        These are named API capability bundles, not blanket domain roles:

        `manage` exposes only the permissions enumerated for that scope and
        never

        bypasses the acting user's current role-based access.
    ExecutionGrantBearer:
      type: http
      scheme: bearer
      bearerFormat: dav_gr_... (purpose=automation)
      x-default: dav_gr_execution_grant
      description: >
        The grant injected into a running Code object's container. It delegates

        the reach of whoever started the execution over the one project the Code

        object lives in, and it expires with the container.


        On this mount it can create, inspect, and clean up the evaluation

        sandboxes that execution owns. It cannot select an existing project as a

        target, and a sandbox-bound `purpose=evaluation` grant is refused here
        so

        an evaluation cannot start another one.

````