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

# POST /v1/competitions/{slug}/preflights

> Run submission checks for an immutable competition candidate.

Run submission preflight checks for an uploaded experiment artifact before
submitting it to a competition.

Auth: Droyd API key or signed-in user bearer token plus active app state. Alias:
`POST /api/v1/competitions/{slug}/preflights`. Body requires
`experiment_id`, `agent_version_id`, and `artifact_id`; accepts
`workflow_node_id`, `wallet_id`, user-scoped `client_key`, `checks`, and
`metadata`. `client_key` is idempotent per user. Supported `checks` values are
`static`, `provider`, and `llm`; ORO implements all three. For ORO, static
checks verify uploaded artifact state,
root `agent.py`, the 1,000,000-byte limit, UTF-8, Python syntax, the
single top-level `agent_main(problem_data)` signature, prohibited imports/calls,
file writes, and exact active-suite reward identifiers, long reward-title
content, or distinctive query phrases. Suite-content findings are advisory and
set `details.requires_confirmation=true`.
The ORO `llm` check uses a structured semantic review focused on hardcoded
product ids/names, suite queries, answer lookup tables, hidden reward access,
and encoded answer data. It does not score plagiarism similarity. No
medium/major finding passes; medium/major findings or review unavailability
return an advisory warning with `requires_confirmation=true`.
ORO `provider` checks require locally signed
`X-Hotkey`, `X-Timestamp`, `X-Nonce`, and `X-Signature` headers plus
`wallet_id`; they verify the stored OpenRouter management credential, live ORO
OpenRouter inference-auth state, a successful sync for the currently active
Droyd credential, signed header ownership, provider auth/subnet readiness, that
OpenRouter is ORO's default inference provider, and ORO's authoritative
`can_submit` cooldown state from `GET /v1/miner/agents`. The cooldown request
requires a second, distinct signed envelope in
`X-Droyd-Oro-Cooldown-Hotkey`, `X-Droyd-Oro-Cooldown-Timestamp`,
`X-Droyd-Oro-Cooldown-Nonce`, and `X-Droyd-Oro-Cooldown-Signature`; its nonce
must differ from `X-Nonce`. A passing provider preflight is wallet-bound and
expires after five minutes. Final submit requires another new signature and
nonce.

For NOVA Blueprint, request `checks: ["static", "provider"]` and pass the
caller-owned local Bittensor `wallet_id`. Static checks require a folder
artifact with root `miner.py`, safe deterministic-ustar paths, no recognized
secret material, no more than 500 files, and no more than 16 MiB uncompressed.
Provider checks use Taostats for SN68 registration and the live MetaNova
`/quote`. The response includes `nova_submission_quote` and
`nova_slot_occupancy`; clients must display the quote and assume an existing
slot may be replaced when occupancy is unavailable. The passed preflight is
bound to the exact competition, experiment, version, artifact, and wallet and
expires after five minutes.


## OpenAPI

````yaml api-key.openapi.json POST /v1/competitions/{slug}/preflights
openapi: 3.1.0
info:
  title: Droyd API-key Automation API
  version: 1.0.0
  description: >-
    The production API contract for Droyd API-key automations. It contains only
    operations that accept a Droyd API key. `/v1` is canonical; `/api/v1` is a
    compatibility alias.
servers: []
security:
  - droydApiKeyBearer: []
  - droydApiKeyHeader: []
tags:
  - name: Identity
    description: Account-scoped automation identity and onboarding state.
  - name: Workflows
    description: Caller-owned workflows and research nodes.
  - name: Competitions
    description: Competition readiness, submissions, and race entries.
  - name: Experiments
    description: Experiments, artifacts, agent versions, and evaluations.
  - name: Usage
    description: Caller-owned evaluation usage.
  - name: Billing
    description: Caller-owned prepaid credit balances and funding.
paths:
  /v1/competitions/{slug}/preflights:
    post:
      tags:
        - Competitions
      summary: Run submission checks for an immutable candidate.
      operationId: createCompetitionPreflight
      parameters:
        - $ref: '#/components/parameters/Slug'
      requestBody:
        $ref: '#/components/requestBodies/CompetitionPreflight'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '201':
          $ref: '#/components/responses/Success'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    Slug:
      name: slug
      in: path
      required: true
      schema:
        type: string
        minLength: 1
  requestBodies:
    CompetitionPreflight:
      required: true
      content:
        application/json:
          schema:
            type: object
            required:
              - experiment_id
              - agent_version_id
              - artifact_id
            properties:
              experiment_id:
                type: string
                format: uuid
              agent_version_id:
                type: string
                format: uuid
              artifact_id:
                type: string
                format: uuid
              wallet_id:
                type: string
                format: uuid
              workflow_node_id:
                type: string
                format: uuid
              client_key:
                type: string
              checks:
                type: array
                items:
                  type: string
                  enum:
                    - static
                    - llm
                    - provider
              metadata:
                type: object
                additionalProperties: true
  responses:
    Success:
      description: Successful response.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SuccessEnvelope'
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: Account state or route policy prevents the request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: The resource is missing or not owned by the API-key account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Conflict:
      description: The resource state or idempotency key conflicts with the request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    ServerError:
      description: >-
        The request could not be completed. Retry only when the operation's
        idempotency contract permits it.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  schemas:
    SuccessEnvelope:
      type: object
      required:
        - ok
      properties:
        ok:
          const: true
      additionalProperties: true
    ErrorEnvelope:
      type: object
      required:
        - ok
        - error
      properties:
        ok:
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string
  securitySchemes:
    droydApiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: Droyd API key
      description: A Droyd API key in the Authorization Bearer slot.
    droydApiKeyHeader:
      type: apiKey
      in: header
      name: x-droyd-api-key
      description: A Droyd API key when Authorization is absent.

````