> ## 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}/configure-credentials

> Configure a competition-specific credential for API-key automation.

Configure a credential required by a competition. For ORO, this registers an
OpenRouter management key for the selected Bittensor wallet.

Auth: Droyd API key or signed-in user bearer token plus active app state. Alias:
`POST /api/v1/competitions/{slug}/configure-credentials`.

Body: `credential_type` is required. Currently supported:
`openrouter_management` for ORO. Provide exactly one of `api_key` or
`credential_id`. `wallet_id` is required for ORO. `label` and `metadata` are
optional when storing a new `api_key`.
OpenRouter management keys must begin with `sk-or-v1-` and are limited to 8192
characters.

ORO requirements: include signed local Bittensor headers `X-Hotkey`,
`X-Timestamp`, `X-Nonce`, and `X-Signature`. Droyd validates that `X-Hotkey`
matches the selected Droyd-registered Bittensor wallet, stores or decrypts the
OpenRouter management key server-side, forwards `{ credential }` to ORO
`POST /v1/miner/inference-auth/openrouter`, then makes OpenRouter the default
through `PATCH /v1/miner/inference-auth/default`. The PATCH uses a second signed
envelope supplied as `X-Droyd-Oro-Default-Provider-Hotkey`,
`X-Droyd-Oro-Default-Provider-Timestamp`,
`X-Droyd-Oro-Default-Provider-Nonce`, and
`X-Droyd-Oro-Default-Provider-Signature`; its nonce must differ from the primary
`X-Nonce`. Droyd records
`competition_provider_connections` with the synced credential id. ORO preflight
requires that id to match the currently active Droyd management credential and
blocks if OpenRouter is no longer the ORO default.

The response returns credential and connection metadata only. It never returns
plaintext secrets, encrypted ciphertext, raw signatures, or raw nonces. API-key
callers can configure competition credentials but cannot read stored secret
material back.


## OpenAPI

````yaml api-key.openapi.json POST /v1/competitions/{slug}/configure-credentials
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}/configure-credentials:
    post:
      tags:
        - Competitions
      summary: Configure a credential for one competition.
      operationId: configureCompetitionCredentials
      parameters:
        - $ref: '#/components/parameters/Slug'
      requestBody:
        $ref: '#/components/requestBodies/CompetitionCredential'
      responses:
        '200':
          $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'
        '503':
          $ref: '#/components/responses/ServerError'
components:
  parameters:
    Slug:
      name: slug
      in: path
      required: true
      schema:
        type: string
        minLength: 1
  requestBodies:
    CompetitionCredential:
      required: true
      content:
        application/json:
          schema:
            type: object
            required:
              - credential_type
            description: Provide exactly one of credential_id or api_key.
            properties:
              credential_type:
                type: string
                enum:
                  - openrouter_management
              credential_id:
                type: string
                format: uuid
              api_key:
                type: string
              label:
                type: string
              wallet_id:
                type: string
                format: uuid
              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.

````