---
openapi: 3.0.1
info:
  title: Aho API
  version: v1
  description: |-
    Verifiable Credentials API for issuance, verification, and management.

    ## Documentation

    New to verifiable credentials? These resources will help:

    - [Glossary](/docs/glossary) — Key terms: DID, VC, VP, holder, issuer, verifier, and more
    - [Credential Formats](/docs/formats) — Comparison of JWT-VC, SD-JWT-VC, and mdoc formats
    - [Developer Guides](/developers) — Step-by-step integration tutorials
    - [Verifiable Credentials API Guide](/developers/verifiable-credentials-with-aho) — Issue and verify credentials
    - [Revocation API Guide](/developers/revocation-api) — Revoke and suspend credentials

    ## Base URL

    All API requests are made to the `api` subdomain:

    ```
    https://api.aho.com
    ```

    For example, `/v1/issuer/credentials` becomes `https://api.aho.com/v1/issuer/credentials`.

    ## Authentication

    Different API paths require different authentication methods:

    | Path Prefix | Authentication | Description |
    |-------------|----------------|-------------|
    | `/v1/issuer/*` | Issuer API Key (`X-API-Key` header) | Credential issuance, schemas, data sources, automations |
    | `/v1/verifier/*` | Verifier API Key (`X-API-Key` header) | Presentation requests, verification |
    | `/v1/account/*` | Account API Key (`X-API-Key` header) | Domains, signing keys, webhooks, API key management |
    | `/v1/holder/*` | Bearer Token (`Authorization` header) | Holder wallet operations |
    | `/v1/hooks/*` | Token in URL path | External webhook triggers (no API key needed) |
    | `/v1/health` | None (public) | Health check endpoint |
    | `/v1/schemas` | None (public) | Public schema registry |

    **API Keys:** Obtain from your dashboard under Settings > API Key. Include as `X-API-Key` header.

    **Webhook Tokens:** Generated per-automation via `POST /v1/issuer/automations/{id}/webhook`.
    The token is embedded in the trigger URL for simple external system integration.

    ## Rate Limits

    All API endpoints are rate limited to prevent abuse. Limits are applied per API key.

    | Category | Limit | Applies To |
    |----------|-------|------------|
    | General | 60 requests/minute | All API endpoints |
    | Batch Operations | 30 requests/minute | Bulk credential issuance, batch revocation |
    | Sensitive Operations | 5 requests/minute | Domain creation, signing key creation, API key operations |
    | Automation Triggers | 10 requests/minute | Automation trigger endpoints |
    | Data Source Tests | 5 requests/minute | Data source connection tests |

    When rate limited, the API returns HTTP 429 with a `Retry-After` header indicating seconds to wait.
  contact:
    name: Aho Support
    email: support@aho.com
paths:
  "/v1/account/api_keys":
    get:
      summary: List API keys
      tags:
      - API Keys
      description: |
        List the account's API keys. Each account has one secret key and one publishable key.

        - **Secret keys**: Masked in responses (only first/last characters shown)
        - **Publishable keys**: Full key value always included (browser-safe)
      operationId: account.api_keys.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: a03e65c93283ca7db5cef73257f2abfe54ddff4fa27704cd8a1b9f96002dcbeb
        schema:
          type: string
      responses:
        '200':
          description: API keys retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/ApiKey"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/api_keys/{hashid}":
    parameters:
    - name: hashid
      in: path
      required: true
      description: API key hashid
      schema:
        type: string
    get:
      summary: Get API key details
      tags:
      - API Keys
      description: Retrieve details for a specific API key.
      operationId: account.api_keys.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: bb18b9a7f91d717584d2f60223a201c7bd18e6d03cc6f7097d5f1a4cd2060677
        schema:
          type: string
      responses:
        '200':
          description: API key retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/ApiKey"
        '404':
          description: API key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update API key
      tags:
      - API Keys
      description: |
        Update an API key's allowed sources.

        - **Secret keys**: Set allowed IP addresses/CIDR ranges
        - **Publishable keys**: Set allowed origin URLs

        Pass an empty array to allow all sources (not recommended for production).
      operationId: account.api_keys.update
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 67c7e17f7a869b1de120b454ea32b332ff124f97c18f0d4c90cea8caeca07e2c
        schema:
          type: string
      responses:
        '200':
          description: API key updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/ApiKeyUpdateResponse"
        '404':
          description: API key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateApiKeyParams"
        required: true
  "/v1/account/api_keys/{hashid}/regenerate":
    parameters:
    - name: hashid
      in: path
      required: true
      description: API key hashid
      schema:
        type: string
    post:
      summary: Regenerate API key
      tags:
      - API Keys
      description: |
        Regenerate an API key's value. The old key value stops working immediately.

        **IMPORTANT**: For secret keys, the new value is only returned once in this response.
        Store it securely - you cannot retrieve it again.

        Key settings (allowed_sources) are preserved during regeneration.
      operationId: account.regenerate.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: bd9a72425e67dd2d92c8f06d5291be16fd9516947b0a7c12b43c6bd77aefe109
        schema:
          type: string
      responses:
        '200':
          description: API key regenerated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/ApiKeyRegenerationResponse"
        '404':
          description: API key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/domains":
    post:
      summary: Register a domain
      tags:
      - Domains
      description: |
        Register a new domain for the account. The first domain registered becomes
        the primary domain. New domains start in pending verification status.

        After registration, use the returned verification instructions to add DNS
        records for both TXT (ownership) and CNAME (routing) verification.
      operationId: account.domains.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 90ba308fae047e619d683be83ebe9aade285387cb8f9585c6621e4a6a364f880
        schema:
          type: string
      responses:
        '201':
          description: Domain registered
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    allOf:
                    - "$ref": "#/components/schemas/AccountDomain"
                    - type: object
                      properties:
                        verification:
                          "$ref": "#/components/schemas/AccountDomainVerification"
        '422':
          description: Invalid domain format
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateDomainParams"
    get:
      summary: List domains
      tags:
      - Domains
      description: List all domains for the authenticated account, ordered by primary
        status and creation date.
      operationId: account.domains.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 2a60debbdce28d2cbb36eb630fd500c3625d4b497faeeb7def615f6b9e2564b8
        schema:
          type: string
      - name: txt_status
        in: query
        type: string
        required: false
        description: Filter by TXT verification status
        schema:
          type: string
          enum:
          - pending
          - verified
          - expired
          - suspended
        example: pending
      - name: fully_verified
        in: query
        required: false
        description: Filter to only fully verified domains (true)
        example: 'true'
        schema:
          type: string
      - name: primary
        in: query
        required: false
        description: Filter to only primary domain (true)
        example: 'true'
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: Page number for pagination
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: Domains retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/AccountDomain"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      total_pages:
                        type: integer
                      total_count:
                        type: integer
                      per_page:
                        type: integer
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/domains/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Domain ID
      example: PtFT0ChmkcHqxHURwMIA
      schema:
        type: string
    get:
      summary: Get domain details
      tags:
      - Domains
      description: |
        Get detailed information about a specific domain, including verification
        instructions and current verification status.
      operationId: account.domains.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 726e0fcb5b8445b92d9d0223a0814b779d60d8f95f5d8cc1a02772ecb6da18d3
        schema:
          type: string
      responses:
        '200':
          description: Domain details retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    allOf:
                    - "$ref": "#/components/schemas/AccountDomain"
                    - type: object
                      properties:
                        verification:
                          "$ref": "#/components/schemas/AccountDomainVerification"
        '404':
          description: Domain not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    delete:
      summary: Delete a domain
      tags:
      - Domains
      description: |
        Delete a domain from the account. Cannot delete the primary domain while
        other domains exist - either make another domain primary first, or delete
        all non-primary domains first.
      operationId: account.domains.delete
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 6f12b2621be125c172c449eb2dd082486a94feea22466a33e4699ddedb60874f
        schema:
          type: string
      responses:
        '200':
          description: Domain deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: Cannot delete primary domain
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Domain not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/domains/{id}/verify":
    parameters:
    - name: id
      in: path
      required: true
      description: Domain ID
      example: xB4XnOnUFyHcNUjcakZs
      schema:
        type: string
    post:
      summary: Verify domain
      tags:
      - Domains
      description: |
        Trigger verification checks for both TXT (ownership) and CNAME (routing)
        DNS records. Returns detailed status for each verification type.

        Both verifications must pass for the domain to be considered fully verified.
      operationId: account.domains.verify
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 8d3e6a67cfa8ec2267c1f6e40a0c61459685d959c987b3082b6ba2b578ad4b30
        schema:
          type: string
      responses:
        '200':
          description: Verification status
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DomainVerificationResult"
        '404':
          description: Domain not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/signing_keys":
    post:
      summary: Generate a signing key
      tags:
      - Signing Keys
      description: |
        Generate a new cryptographic signing key for the account. The private key
        is stored encrypted at rest and never exposed via the API.

        By default, creates an ES256 (ECDSA P-256) key and activates it immediately.
      operationId: account.signing_keys.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: fd363c71749535894063bae29b079e00ddf9047225c226a2548e21a615b12c09
        schema:
          type: string
      responses:
        '201':
          description: Signing key created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/SigningKeyDetails"
        '422':
          description: Unsupported algorithm
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateSigningKeyParams"
    get:
      summary: List signing keys
      tags:
      - Signing Keys
      description: List all signing keys for the authenticated account.
      operationId: account.signing_keys.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: c0e86f173b7c1edf3538a25386eb988caf38972075078e8e2595cc22fa7c4b23
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - pending
          - active
          - revoked
          - expired
        example: pending
      - name: algorithm
        in: query
        type: string
        required: false
        description: Filter by algorithm
        schema:
          type: string
          enum:
          - es256
          - es384
          - ed25519
        example: es256
      - name: usable
        in: query
        required: false
        description: Filter to only usable keys (true)
        example: 'true'
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: Page number
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: Signing keys retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/SigningKey"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      total_pages:
                        type: integer
                      total_count:
                        type: integer
                      per_page:
                        type: integer
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/signing_keys/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Signing key ID or key_id
      example: key-edcb3c63-2bda-4418-867f-d51d761d7607
      schema:
        type: string
    get:
      summary: Get signing key details
      tags:
      - Signing Keys
      description: |
        Get detailed information about a signing key including its public JWK,
        active certificates, and DID-related identifiers.
      operationId: account.signing_keys.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 7024fa960ae9df67e69ddfd5f27b9da4f337f01329c70c79d8c9dd811cf58c51
        schema:
          type: string
      responses:
        '200':
          description: Signing key details retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/SigningKeyDetails"
        '404':
          description: Signing key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/signing_keys/{id}/rotate":
    parameters:
    - name: id
      in: path
      required: true
      description: Signing key ID or key_id
      example: key-62a20d2c-2025-449c-886f-a4a3c42f6e1c
      schema:
        type: string
    post:
      summary: Rotate a signing key
      tags:
      - Signing Keys
      description: |
        Rotate a signing key by revoking the old key and creating a new one.
        Only active keys can be rotated. The new key inherits the same algorithm
        unless specified otherwise.
      operationId: account.signing_keys.rotate
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: e65fdeaf62b97f79ec1ccf27e4cbcbbbe994736529d0f65b1dccaf3b8a8c7dde
        schema:
          type: string
      responses:
        '200':
          description: Key rotated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/KeyRotationResult"
        '422':
          description: Cannot rotate non-active key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Signing key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RotateSigningKeyParams"
  "/v1/account/signing_keys/{id}/revoke":
    parameters:
    - name: id
      in: path
      required: true
      description: Signing key ID or key_id
      example: key-f847921b-039d-4c48-a739-1ebb972684c0
      schema:
        type: string
    post:
      summary: Revoke a signing key
      tags:
      - Signing Keys
      description: |
        Revoke a signing key. Revoked keys can no longer be used for signing,
        but credentials signed before revocation remain verifiable.
      operationId: account.signing_keys.revoke
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 3cc44625374555b6a61fce7878bc7a23fe50ade37d5547e6fc7b321f6f96399e
        schema:
          type: string
      responses:
        '200':
          description: Key revoked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      key:
                        "$ref": "#/components/schemas/SigningKey"
        '422':
          description: Key already revoked
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Signing key not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/signing_keys/{id}/certificate":
    parameters:
    - name: id
      in: path
      required: true
      description: Signing key ID or key_id
      example: key-0f0c9bab-eb3c-44e8-9b08-19fe380d4153
      schema:
        type: string
    get:
      summary: Download X.509 certificate
      tags:
      - Signing Keys
      description: |
        Download the X.509 certificate for a signing key. By default returns the
        certificate for the primary domain. Specify a domain parameter to get the
        certificate for a specific domain.
      operationId: account.signing_keys.certificate
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: de05e9d1a2c791781564d14845ce46bdd9a0fa5d8876d816fee8526cba321831
        schema:
          type: string
      - name: domain
        in: query
        required: false
        description: 'Domain to get certificate for (default: primary domain)'
        example: trust.example.com
        schema:
          type: string
      responses:
        '200':
          description: Certificate retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CertificateResponse"
        '404':
          description: No certificate found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/webhooks":
    get:
      summary: List webhooks
      tags:
      - Webhooks
      description: |
        List configured webhooks for the account. Currently each account can have
        at most one webhook, so this returns either an empty array or a single-item array.
      operationId: account.webhooks.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 87a1999298233108d238226842f38f76e29716f5a1653e99b7a9df1355a89ea9
        schema:
          type: string
      responses:
        '200':
          description: Webhooks retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Webhook"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Create webhook
      tags:
      - Webhooks
      description: |
        Configure a webhook endpoint to receive event notifications. The account
        can only have one webhook at a time - use PATCH to update an existing webhook.

        Events sent to the webhook include:
        - credential.issued - When a new credential is issued
        - credential.revoked - When a credential is revoked
        - presentation.verified - When a presentation is verified (verifiers only)
      operationId: account.webhooks.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 8c44fe73dd60eb9098d491d03864a2309032c43892ed9d2b06a291833789a02f
        schema:
          type: string
      responses:
        '201':
          description: Webhook created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/Webhook"
        '422':
          description: Webhook already exists
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateWebhookParams"
  "/v1/account/webhooks/primary":
    get:
      summary: Get webhook details
      tags:
      - Webhooks
      description: Get details of the configured webhook.
      operationId: account.webhooks.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: f5a1db27f8c4ca8b6f753340cc21f5f3d59abbf7137ed71319ff3d8873d94362
        schema:
          type: string
      responses:
        '200':
          description: Webhook details retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/Webhook"
        '404':
          description: Webhook not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update webhook
      tags:
      - Webhooks
      description: Update the webhook endpoint URL.
      operationId: account.webhooks.update
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: a13b79a3b4fa46954c47b0ddd8a64edd57e94cdc35df47be1817dd8b525ba7cc
        schema:
          type: string
      responses:
        '200':
          description: Webhook updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/Webhook"
        '404':
          description: Webhook not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateWebhookParams"
    delete:
      summary: Delete webhook
      tags:
      - Webhooks
      description: Remove the webhook configuration. The account will no longer receive
        event notifications.
      operationId: account.webhooks.delete
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: adc4ad9a9aa77503a38cc0136d01d5601b9fb572554b7095f8deb5ba72c6a97e
        schema:
          type: string
      responses:
        '200':
          description: Webhook removed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '404':
          description: Webhook not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/account/webhooks/primary/test":
    post:
      summary: Test webhook
      tags:
      - Webhooks
      description: |
        Send a test webhook to verify the endpoint is working correctly.
        Returns the HTTP status code received from the endpoint.
      operationId: account.webhooks.test
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for authentication
        example: 2f16a442e037f202812215c7190507fb0748afa745a3cb580f7e88d7f56e6a92
        schema:
          type: string
      responses:
        '200':
          description: Test webhook sent
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/WebhookTestResult"
        '404':
          description: Webhook not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/health":
    get:
      summary: Health check
      tags:
      - System
      description: |
        Public health check endpoint. Returns the current server status and timestamp.
        No authentication required. Useful for load balancers and monitoring systems.
      operationId: system.health.get
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  timestamp:
                    type: string
                    format: date-time
                required:
                - status
                - timestamp
  "/v1/holder/credentials":
    get:
      summary: List holder credentials
      tags:
      - Credentials
      description: |
        List all credentials accessible to the authenticated holder. This includes credentials
        where the holder is the designated holder_account, the subject identifier matches their
        email, or the credential is bound to one of their signing keys.
      operationId: holder.credentials.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: 112511beb3783184d4c836009ab9092e47120d47c5928d89711dfcc96c34c0b5
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: 'Page number for pagination (default: 1)'
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      - name: status
        in: query
        type: string
        required: false
        description: Filter by credential status
        schema:
          type: string
          enum:
          - active
          - suspended
          - revoked
          - expired
          - archived
        example: active
      - name: sort
        in: query
        type: string
        required: false
        description: Sort field
        schema:
          type: string
          enum:
          - status
          - issued_at
          - expires_at
          - created_at
        example: created_at
      - name: direction
        in: query
        type: string
        required: false
        description: 'Sort direction (default: desc)'
        schema:
          type: string
          enum:
          - asc
          - desc
        example: desc
      responses:
        '200':
          description: List of credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        uuid:
                          type: string
                          format: uuid
                        status:
                          type: string
                        type:
                          type: string
                        type_display:
                          type: string
                        schema:
                          "$ref": "#/components/schemas/SchemaRef"
                        issuer:
                          type: object
                          properties:
                            name:
                              type: string
                            did:
                              type: string
                            domain:
                              type: string
                              nullable: true
                        issued_at:
                          type: string
                          format: date-time
                        expires_at:
                          type: string
                          format: date-time
                          nullable: true
                        created_at:
                          type: string
                          format: date-time
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/holder/credentials/{uuid}":
    get:
      summary: Get holder credential details
      tags:
      - Credentials
      description: |
        Retrieve details of a specific credential including the full claims.
        Only accessible if the holder has access to this credential.
      operationId: holder.credentials.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: 23d043cf4c6ca14064053043b4bb6ff467cab2a11af9eb4b4335d96e6afc75de
        schema:
          type: string
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: cfcba9d7-f9dc-42cb-8fda-90a0cf62f72b
        schema:
          type: string
      responses:
        '200':
          description: Credential details with claims
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      uuid:
                        type: string
                        format: uuid
                      status:
                        type: string
                      type:
                        type: string
                      type_display:
                        type: string
                      schema:
                        "$ref": "#/components/schemas/SchemaRef"
                      issuer:
                        type: object
                        properties:
                          name:
                            type: string
                          did:
                            type: string
                          domain:
                            type: string
                            nullable: true
                      issued_at:
                        type: string
                        format: date-time
                      expires_at:
                        type: string
                        format: date-time
                        nullable: true
                      created_at:
                        type: string
                        format: date-time
                      claims:
                        type: object
                        additionalProperties: true
                        description: Full credential claims (only included in show)
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Credential not accessible to holder
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/holder/presentations":
    get:
      summary: List holder presentations
      tags:
      - Presentations
      description: |
        List all presentations created by the authenticated holder. Returns presentations
        in descending order by creation date, with pagination support.
      operationId: holder.presentations.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: f61426a0417fb2edb680849f9ed8c6254cbeac04575ef99f10c2a278d51a7428
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: 'Page number for pagination (default: 1)'
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      - name: status
        in: query
        type: string
        required: false
        description: Filter by presentation status
        schema:
          type: string
          enum:
          - active
          - expired
          - revoked
        example: active
      - name: credential_uuid
        in: query
        required: false
        description: Filter presentations by credential UUID
        example: c3f46c07-c95e-4ff8-9286-c49ccdb13cf9
        schema:
          type: string
      - name: sort
        in: query
        type: string
        required: false
        description: Sort field
        schema:
          type: string
          enum:
          - status
          - expires_at
          - created_at
        example: created_at
      - name: direction
        in: query
        type: string
        required: false
        description: 'Sort direction (default: desc)'
        schema:
          type: string
          enum:
          - asc
          - desc
        example: desc
      responses:
        '200':
          description: List of presentations
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Presentation"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Create a credential presentation
      tags:
      - Presentations
      description: |
        Create a selective disclosure presentation from a credential. This allows holders to share
        only specific claims with verifiers while proving the credential's authenticity.
      operationId: holder.presentations.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: 879211ec030dbe3131c858cb617223fce74f504d9c5aabc3d24496478f065545
        schema:
          type: string
      responses:
        '201':
          description: Presentation created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/Presentation"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Credential does not belong to holder
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreatePresentationParams"
  "/v1/holder/presentations/{uuid}":
    get:
      summary: Get presentation details
      tags:
      - Presentations
      description: Retrieve details of a specific presentation by UUID.
      operationId: holder.presentations.get
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation UUID
        example: 35e1d441-2ea6-45bc-bbe4-6e07b17e354e
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: 4fa1dba2b825d495bebe9ccc6dda7dd6597de3974681e6bf3cb9b2a0f59de93c
        schema:
          type: string
      responses:
        '200':
          description: Presentation details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/Presentation"
        '404':
          description: Presentation not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    delete:
      summary: Revoke a presentation
      tags:
      - Presentations
      description: Revoke a presentation so it can no longer be verified.
      operationId: holder.presentations.delete
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation UUID
        example: 20bc82d3-c8ec-4204-99a8-cb67396bc28a
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for holder authentication
        example: b44831335c1cb545eccac363a2f9bb5b47b186057ce3207fd69adf6daa3c750b
        schema:
          type: string
      responses:
        '200':
          description: Presentation revoked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '404':
          description: Presentation not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/presentations/verify":
    post:
      summary: Verify a presentation
      tags:
      - Presentations
      description: |
        Verify a credential presentation. This is a public endpoint that can be called by anyone
        with the presentation UUID or token. Returns the disclosed claims if the presentation is valid.
      operationId: verifier.presentations.verify
      parameters: []
      responses:
        '200':
          description: Presentation not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PresentationVerifyResult"
        '400':
          description: Missing required parameter
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VerifyPresentationParams"
  "/v1/hooks/automations/{token}":
    post:
      summary: Trigger a credential automation via webhook
      tags:
      - Hooks
      description: |
        **External systems call this endpoint to trigger credential issuance.**

        **Example use case:** Your HR system calls this URL when an employee is promoted,
        triggering automatic issuance of a new title credential.

        **Requirements:**
        - Automation must have `trigger_mode: webhook` and `status: active`
        - Valid webhook token in the URL path

        **Authentication:** Token-based (in URL), no API key or headers required.
        This allows simple integration with systems that only support basic webhook callbacks.

        **Rate limit:** 10 requests per minute per automation.

        **Get your trigger URL:** `GET /v1/issuer/automations/{id}/webhook` (requires API key).
      operationId: hooks.automations.trigger
      parameters:
      - name: token
        in: path
        required: true
        description: Webhook token for the automation
        example: MtchCMx8ZF346iWxXz38xUtBYf5CsICYvQ8PJHk5gqk
        schema:
          type: string
      responses:
        '200':
          description: Automation run triggered successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Automation run triggered successfully
                  data:
                    type: object
                    properties:
                      automation_id:
                        type: string
                        description: Hashid identifier
                        example: nZaPYEp78T82P57z0NRl
                      automation_name:
                        type: string
                        example: Daily Diploma Issuance
                      triggered_at:
                        type: string
                        format: date-time
                      status:
                        type: string
                        example: queued
        '401':
          description: Unauthorized - Invalid webhook token
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: Forbidden - Webhook not enabled or automation not active
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '503':
          description: Service Unavailable - Run already in progress
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '429':
          description: Too Many Requests - Rate limit exceeded
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/automations/{automation_id}/webhook":
    parameters:
    - name: automation_id
      in: path
      required: true
      description: Automation ID
      example: EGS6oeoYVbtgWjaflnyi
      schema:
        type: string
    get:
      summary: Get webhook configuration
      tags:
      - Automations
      description: |
        Get the webhook trigger URL and token for an automation.

        **Use case:** Configure external systems (HR software, LMS, etc.) to call the `trigger_url`
        when data changes, automatically issuing credentials.

        The `trigger_url` includes the token and can be called without API key authentication.
        The automation must have `trigger_mode: webhook` and `status: active` for triggers to work.
      operationId: issuer.automations.get_webhook
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 4aeaaddc789bd2436018021989810cddb948be47fc9abe2d4459c3f8502b5f78
        schema:
          type: string
      responses:
        '200':
          description: Webhook configuration
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/AutomationWebhook"
        '404':
          description: No webhook configured
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Generate webhook token
      tags:
      - Automations
      description: |
        Generate a webhook token for an automation, enabling external trigger capability.

        **If a token already exists**, calling this endpoint replaces it with a new one.
        The old token immediately stops working—update your external systems with the new URL.

        **Security:** Tokens are long random strings. Treat the `trigger_url` as a secret.
        If compromised, regenerate the token to invalidate the old URL.
      operationId: issuer.automations.create_webhook
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: aab699795284176ec4b2fe13d8cffb72d73fc802ffe73659da401dd6e1667246
        schema:
          type: string
      responses:
        '201':
          description: Webhook token generated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/AutomationWebhook"
        '404':
          description: Automation not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    delete:
      summary: Revoke webhook token
      tags:
      - Automations
      description: |
        Revoke the webhook token, disabling external webhook triggers for this automation.

        **Use case:** Disable webhook capability entirely, or as an emergency measure if the token is compromised.

        After revocation, the automation can still be triggered via API (with `POST /trigger`) or on schedule.
        To re-enable webhooks, generate a new token with POST.
      operationId: issuer.automations.delete_webhook
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: e23954b80b7033b9a6a5d52ad2fdf24452de50f0354cfdc14169d4f2f5a63308
        schema:
          type: string
      responses:
        '200':
          description: Webhook token revoked
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '404':
          description: No webhook configured
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/automations":
    post:
      summary: Create an automation
      tags:
      - Automations
      description: |
        Create a new credential automation. Automations define when and how
        credentials are automatically issued from a data source mapping.
      operationId: issuer.automations.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 7c437bddcefe07cea745148a3678286c2e39ee36f146498d7ceb9db232974267
        schema:
          type: string
      responses:
        '201':
          description: Automation created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialAutomation"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateAutomationParams"
    get:
      summary: List automations
      tags:
      - Automations
      description: List all credential automations for the authenticated issuer.
      operationId: issuer.automations.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: dae2f16a60a6ad49e4b91a2d9385725b7e496590b5aeaa2313bdaa34d4520c49
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - draft
          - active
          - paused
          - error
        example: draft
      - name: trigger_mode
        in: query
        type: string
        required: false
        description: Filter by trigger mode
        schema:
          type: string
          enum:
          - manual
          - scheduled
          - webhook
        example: manual
      - name: page
        in: query
        required: false
        description: Page number for pagination
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of automations
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CredentialAutomation"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      per_page:
                        type: integer
                      total_count:
                        type: integer
                      total_pages:
                        type: integer
  "/v1/issuer/automations/{id}":
    get:
      summary: Get automation details
      tags:
      - Automations
      description: Retrieve detailed information about a specific automation.
      operationId: issuer.automations.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 3c082c9f032470145c67a029ac48f4378c7e769ef18ad445cadcfb992aeb3141
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: n8fY6GvShyRgg5CoQWKd
        schema:
          type: string
      responses:
        '200':
          description: Automation details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialAutomation"
        '404':
          description: Not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update an automation
      tags:
      - Automations
      description: Update automation properties. Only provided fields are updated.
      operationId: issuer.automations.update
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: c8234f565f2cfd83df0f3f3f047ad0ca59f435c18682507ec358faf3088b32cf
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: 2f2iiVPQXIELWn3UOSFg
        schema:
          type: string
      responses:
        '200':
          description: Automation updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialAutomation"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateAutomationParams"
    delete:
      summary: Delete an automation
      tags:
      - Automations
      description: Delete a credential automation.
      operationId: issuer.automations.delete
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: f7c9f79909a631f74d43fcb8a5558b9eb7382583e8b703679f31f0f6bb803cb0
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: SOoejdKoepguKbf3wpgX
        schema:
          type: string
      responses:
        '200':
          description: Automation deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
  "/v1/issuer/automations/{id}/trigger":
    post:
      summary: Trigger an automation
      tags:
      - Automations
      description: |
        Manually trigger an automation to run. The automation must be in active status.
        Returns immediately with a run ID - actual execution happens in the background.
      operationId: issuer.automations.trigger
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 2010ab4e1c4e648381e4220b4d1399741d6a81688f0b91b62fd76137b62c85a3
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: tdQyPTSLFkq1I9kwPVnK
        schema:
          type: string
      responses:
        '200':
          description: Automation triggered
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/AutomationTriggerResult"
        '422':
          description: Automation not active
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/automations/{id}/pause":
    post:
      summary: Pause an automation
      tags:
      - Automations
      description: Pause an active automation. Only active automations can be paused.
      operationId: issuer.automations.pause
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 6f0c48c3bc85aaa7358d18ac1cdd3c8fb52c3ed2fe199bc23c3268e69c05772a
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: rTkMkqNKiW4xABgxMXHE
        schema:
          type: string
      responses:
        '200':
          description: Automation paused
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialAutomation"
  "/v1/issuer/automations/{id}/resume":
    post:
      summary: Resume an automation
      tags:
      - Automations
      description: Resume a paused automation. Only paused automations can be resumed.
      operationId: issuer.automations.resume
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 45593374dd01bf36dfb504488381d5f14a979dbb19dc4c1f4f6bcc952a5ad615
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Automation ID
        example: 5ZhNi9NrbVLlnAZFI95S
        schema:
          type: string
      responses:
        '200':
          description: Automation resumed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialAutomation"
  "/v1/issuer/credentials":
    post:
      summary: Issue a new credential
      tags:
      - Credential Issuances
      description: |
        Issue a new verifiable credential to a holder. Requires issuer authentication via API key or bearer token.
        The credential is signed and stored, ready for the holder to claim.
      operationId: issuer.credentials.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 8b6369b4c7707b85d75c884dbdb238239d1865e9cbd153df2d4ba15f9eba37a9
        schema:
          type: string
      responses:
        '201':
          description: Credential created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialIssuance"
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateCredentialParams"
    get:
      summary: List credentials
      tags:
      - Credential Issuances
      description: |
        List all credentials issued by the authenticated issuer. Supports filtering by status,
        schema, holder identifier, and date ranges. Results are paginated and sortable.
      operationId: issuer.credentials.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 53b709ad1f63b63983778fff795143f2272340b2e702c0ca21c610ae8c7ce6ed
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by credential status
        schema:
          type: string
          enum:
          - active
          - suspended
          - revoked
          - expired
          - archived
        example: active
      - name: schema
        in: query
        required: false
        description: Filter by schema UUID or slug
        example: 43fc015e-1c3b-41a7-b19e-877c6214800e
        schema:
          type: string
      - name: subject_identifier
        in: query
        required: false
        description: Filter by holder identifier (exact match)
        example: employee@example.com
        schema:
          type: string
      - name: issued_after
        in: query
        format: date-time
        required: false
        description: 'Filter by issued_at >= this date (ISO8601). Note: uses issued_at,
          not created_at.'
        example: '2025-01-01T00:00:00Z'
        schema:
          type: string
      - name: issued_before
        in: query
        format: date-time
        required: false
        description: 'Filter by issued_at <= this date (ISO8601). Note: uses issued_at,
          not created_at.'
        example: '2026-12-31T23:59:59Z'
        schema:
          type: string
      - name: expires_after
        in: query
        format: date-time
        required: false
        description: Filter credentials expiring after this date (ISO8601)
        example: '2027-01-01T00:00:00Z'
        schema:
          type: string
      - name: expires_before
        in: query
        format: date-time
        required: false
        description: Filter credentials expiring before this date (ISO8601)
        example: '2028-12-31T23:59:59Z'
        schema:
          type: string
      - name: sort
        in: query
        type: string
        required: false
        description: Sort column
        schema:
          type: string
          enum:
          - issued_at
          - expires_at
          - subject_identifier
          - status
          - created_at
          default: issued_at
        example: issued_at
      - name: direction
        in: query
        type: string
        required: false
        description: Sort direction
        schema:
          type: string
          enum:
          - asc
          - desc
          default: desc
        example: desc
      - name: page
        in: query
        required: false
        description: Page number for pagination
        default: 1
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: Number of results per page (max 100)
        default: 25
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CredentialIssuance"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/{uuid}":
    get:
      summary: Get issued credential details
      tags:
      - Credential Issuances
      description: Retrieve details of a specific credential by ID or UUID.
      operationId: issuer.credentials.get
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: b8bdca66-dde8-4db6-ac87-156ad7d1be3c
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: cfed6e59149d99670810807a2db3a45890a2961df9a39b79718392103a3ce5c1
        schema:
          type: string
      responses:
        '200':
          description: Credential details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialIssuance"
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/{uuid}/revoke":
    post:
      summary: Revoke a credential
      tags:
      - Credential Issuances
      description: |
        Permanently revoke a credential. Once revoked, the credential will fail verification.
        A revocation reason is required for audit purposes.
      operationId: issuer.credentials.revoke
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: c3855341-2abe-4291-94fb-f17e9184c972
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: cf601aff68dd62dfa69f6f3923e31990f27cb633100bc0edcdd3e4c3a7641da8
        schema:
          type: string
      responses:
        '200':
          description: Credential issuance revoked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Whether the operation succeeded
                  data:
                    type: object
                    properties:
                      credential:
                        "$ref": "#/components/schemas/CredentialIssuance"
                      message:
                        type: string
                        description: Human-readable confirmation message
                        example: Credential issuance has been revoked
        '400':
          description: Missing revocation reason
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RevokeCredentialParams"
  "/v1/issuer/credentials/{uuid}/suspend":
    post:
      summary: Suspend a credential
      tags:
      - Credential Issuances
      description: |
        Temporarily suspend a credential. Suspended credentials will fail verification but can be
        reactivated later. Use this for temporary holds or investigations.
      operationId: issuer.credentials.suspend
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: 305c3e38-336e-491f-b753-d288e5ec83c0
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 4f3eb1b8cde8e01fd0925b56d2df14bab7398ba54c729650a4472ca1875aa1da
        schema:
          type: string
      responses:
        '200':
          description: Credential issuance suspended successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Whether the operation succeeded
                  data:
                    type: object
                    properties:
                      credential:
                        "$ref": "#/components/schemas/CredentialIssuance"
                      message:
                        type: string
                        description: Human-readable confirmation message
                        example: Credential issuance has been suspended
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/{uuid}/reinstate":
    post:
      summary: Reinstate a suspended credential
      tags:
      - Credential Issuances
      description: |
        Reinstate a previously suspended credential. Only suspended credentials can be reinstated.
        Revoked and pending credentials cannot be reinstated.
      operationId: issuer.credentials.reinstate
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: ec5a84a1-bbec-46dd-bbb5-815205d8151e
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 0ede08e59c9b8fb3f516152f565b713285119ea64d11427d7bbea9f5e9755cf9
        schema:
          type: string
      responses:
        '200':
          description: Credential reinstated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      credential:
                        "$ref": "#/components/schemas/CredentialIssuance"
                      message:
                        type: string
                        example: Credential reinstated successfully
        '422':
          description: Cannot reinstate revoked credential
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/{uuid}/status":
    get:
      summary: Get credential status
      tags:
      - Credential Issuances
      description: |
        Get the current status of a credential. This is a lightweight endpoint for polling
        credential status without retrieving full credential details.
      operationId: issuer.credentials.status
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: f059b7be-3a2a-4fda-a4ca-42ca79da2d9d
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: c9c8b6231e97b57cfa0d25184e4d222f33ade439c18804232d54c53bcf127d58
        schema:
          type: string
      responses:
        '200':
          description: Credential status
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      credential:
                        type: object
                        properties:
                          uuid:
                            type: string
                          status:
                            type: string
                            enum:
                            - pending
                            - issued
                            - suspended
                            - revoked
                          revocation_reason:
                            type: string
                            nullable: true
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/{uuid}/history":
    get:
      summary: Get credential history
      tags:
      - Credential Issuances
      description: |
        Get the audit trail for a credential. Returns all status changes and modifications
        tracked via Paper Trail for compliance purposes.
      operationId: issuer.credentials.history
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential UUID
        example: 02df4bd0-97d1-4147-bc7f-61bfb7a6cb3e
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: be6607b92d23bdc69d944ade6700d2d288e698695abcfcfb2bb76821a2e3de21
        schema:
          type: string
      responses:
        '200':
          description: Credential history
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      credential_uuid:
                        type: string
                      versions:
                        type: array
                        items:
                          type: object
                          properties:
                            version_id:
                              type: integer
                            version_number:
                              type: integer
                            event:
                              type: string
                              enum:
                              - create
                              - update
                              - destroy
                            changed_at:
                              type: string
                              format: date-time
                            changes:
                              type: object
                              additionalProperties: true
        '404':
          description: Credential not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/credentials/revoke_batch":
    post:
      summary: Revoke multiple credentials
      tags:
      - Credential Issuances
      description: |
        Revoke multiple credentials in a single request. Returns per-UUID results for debugging
        and summary counts for quick status checks.

        Limit: Maximum 100 UUIDs per request.
      operationId: issuer.credentials.revoke_batch
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 03c8ca9548edc65054c24b59379b486756ae1031d18e911f42a3d83ca11db76e
        schema:
          type: string
      responses:
        '200':
          description: Batch revocation results
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/BatchOperationResult"
        '422':
          description: Invalid request - empty array
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RevokeBatchParams"
  "/v1/issuer/credentials/suspend_batch":
    post:
      summary: Suspend multiple credentials
      tags:
      - Credential Issuances
      description: |
        Suspend multiple credentials in a single request. Returns per-UUID results for debugging
        and summary counts including suspended, not found, already suspended, and credentials
        that cannot be suspended (revoked/pending).

        Limit: Maximum 100 UUIDs per request.
      operationId: issuer.credentials.suspend_batch
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 8abb062044102397a146160d01a3fcca90f889252b399786563a13dbc78365e8
        schema:
          type: string
      responses:
        '200':
          description: Batch suspension results
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/BatchOperationResult"
        '422':
          description: Invalid request - empty array
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SuspendBatchParams"
  "/v1/issuer/credentials/reinstate_batch":
    post:
      summary: Reinstate multiple credentials
      tags:
      - Credential Issuances
      description: |
        Reinstate multiple suspended credentials in a single request. Returns per-UUID results
        for debugging and summary counts including reinstated, not found, already active, and
        credentials that cannot be reinstated (revoked/pending).

        Limit: Maximum 100 UUIDs per request.
      operationId: issuer.credentials.reinstate_batch
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: e65f44b18538f2895d3f52c759609fcd5a210365e5616ae00b1277f7ac287a68
        schema:
          type: string
      responses:
        '200':
          description: Batch reinstatement results
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/BatchOperationResult"
        '422':
          description: Invalid request - empty array
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReinstateBatchParams"
  "/v1/issuer/data_source_mappings":
    post:
      summary: Create a data source mapping
      tags:
      - Data Source Mappings
      description: |
        Create a mapping that connects a data source to a credential schema.

        **What this does:**
        - Links a data source (e.g., your employee database) to a credential schema (e.g., EmployeeBadge)
        - Defines field mappings: which database columns populate which credential claims
        - Configures how to query records from the source

        **Example:** Map `employees.full_name` → credential `name` claim, `employees.job_title` → `title` claim.

        Once created, use this mapping with an Automation to automatically issue credentials.
      operationId: issuer.data_source_mappings.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 02a1036db0c4c37dc6abd41e745d35612b55b2ab8540d2200dda2b679bf61766
        schema:
          type: string
      responses:
        '201':
          description: Mapping created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSourceMapping"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateDataSourceMappingParams"
    get:
      summary: List data source mappings
      tags:
      - Data Source Mappings
      description: |
        List all data source mappings. Filter by data source or credential schema to find specific mappings.

        Use this to see which data sources are connected to which credential schemas.
      operationId: issuer.data_source_mappings.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: e4521810c8aabf3ab6047b3877a812b34c6497087258159a046841dce0b4d2f7
        schema:
          type: string
      - name: data_source
        in: query
        required: false
        description: Filter by data source slug or ID
        example: employee-database
        schema:
          type: string
      - name: credential_schema
        in: query
        required: false
        description: Filter by credential schema slug or ID
        example: employee-badge
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: Page number for pagination
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of mappings
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/DataSourceMapping"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      per_page:
                        type: integer
                      total_count:
                        type: integer
                      total_pages:
                        type: integer
  "/v1/issuer/data_source_mappings/{id}":
    get:
      summary: Get mapping details
      tags:
      - Data Source Mappings
      description: Retrieve detailed information about a specific mapping, including
        field_mapping and query_config.
      operationId: issuer.data_source_mappings.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 7b1daf201b2b36696146234972a6a0f1768e068f38c51cb8ee8b380da5d41d90
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source mapping ID
        example: udGKSGFYFYN7c6aqgURA
        schema:
          type: string
      responses:
        '200':
          description: Mapping details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSourceMapping"
        '404':
          description: Not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update a mapping
      tags:
      - Data Source Mappings
      description: Update mapping properties. Only provided fields are updated.
      operationId: issuer.data_source_mappings.update
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 17b4ce6f327f3ac44f5867f356cf318ddba69b47fa44f2071456a8ecb3cd3cf7
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source mapping ID
        example: ScfmD1gFrkUdT9ziHz04
        schema:
          type: string
      responses:
        '200':
          description: Mapping updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSourceMapping"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateDataSourceMappingParams"
    delete:
      summary: Delete a mapping
      tags:
      - Data Source Mappings
      description: |
        Delete a data source mapping. This operation will fail if the mapping has
        active credential automations. Remove all automations first.
      operationId: issuer.data_source_mappings.delete
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 53e52a67fc7fb2a8acde2d320bc5ed1ce1577c325d25a9ec897fa0b39ac6caf5
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source mapping ID
        example: kyD6GNHzFXmIc6JnoJ85
        schema:
          type: string
      responses:
        '200':
          description: Mapping deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: Cannot delete with automations
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/data_sources":
    post:
      summary: Create a data source
      tags:
      - Data Sources
      description: |
        Create a new data source for automated credential issuance. Data sources
        connect to external databases or file uploads to retrieve subject data.
        New data sources are created in draft status.
      operationId: issuer.data_sources.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: ffd212b3b5fc33364ad9dc32fd710cd5a31d2b292216f71d254c226219459b3a
        schema:
          type: string
      responses:
        '201':
          description: Data source created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSource"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateDataSourceParams"
    get:
      summary: List data sources
      tags:
      - Data Sources
      description: List all data sources for the authenticated issuer.
      operationId: issuer.data_sources.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 8475e62ed683abe539c709352ab11ecf74b48211092f7daabf15afea56596420
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - draft
          - active
          - paused
          - error
        example: draft
      - name: source_type
        in: query
        type: string
        required: false
        description: Filter by source type
        schema:
          type: string
          enum:
          - postgresql
          - csv
        example: postgresql
      - name: page
        in: query
        required: false
        description: Page number for pagination
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: Filtered by status
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/DataSource"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      per_page:
                        type: integer
                      total_count:
                        type: integer
                      total_pages:
                        type: integer
  "/v1/issuer/data_sources/{id}":
    get:
      summary: Get data source details
      tags:
      - Data Sources
      description: Retrieve detailed information about a specific data source, including
        connection metadata (passwords are never exposed).
      operationId: issuer.data_sources.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 47df06404de8d8ab865ade404d62854a608ad7fa446ff26a2aadd877535a3773
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source ID
        example: 7OsMy8FTmeuYZYfCce6N
        schema:
          type: string
      responses:
        '200':
          description: Data source details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSource"
        '404':
          description: Not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update a data source
      tags:
      - Data Sources
      description: Update data source properties. Only provided fields are updated.
      operationId: issuer.data_sources.update
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 4db9a564a5f74a3256788c65aff7ad8070405831f3b10406ee63188484af583f
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source ID
        example: uLNrmLHmI0iEWsVvjDBJ
        schema:
          type: string
      responses:
        '200':
          description: Data source updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSource"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateDataSourceParams"
    delete:
      summary: Delete a data source
      tags:
      - Data Sources
      description: |
        Delete a data source. This operation will fail if the data source has
        active mappings to credential schemas. Remove all mappings first.
      operationId: issuer.data_sources.delete
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: ca16f88af9f0842b12621a9fc5a4b05b020bc0535d0f6d49d599d37dc0b90314
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source ID
        example: SchBSoFscRecj6F4wQER
        schema:
          type: string
      responses:
        '200':
          description: Data source deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: Cannot delete with mappings
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/data_sources/{id}/test":
    post:
      summary: Test data source connection
      tags:
      - Data Sources
      description: |
        Test the connection to the data source. For PostgreSQL sources, this
        attempts to connect using the stored credentials. Updates the data source
        status based on the result (active on success, error on failure).
      operationId: issuer.data_sources.test
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: b6099ce6e96bc0f483a50e1b45f691676447aa02cf6594dbd9b53591a8949975
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Data source ID
        example: YM1yj7eKX588LknvpmJ4
        schema:
          type: string
      responses:
        '200':
          description: Connection test failed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DataSourceTestResult"
  "/v1/issuer/offers":
    get:
      summary: List credential offers
      tags:
      - Credential Offers
      description: |
        List all credential offers created by the issuer. Returns offers in descending
        order by creation date, with pagination support.
      operationId: issuer.offers.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 466736ec98a3e310ddf39268e9a8b8b0a9db89aa7c09ccefcc72eb0dcedd0ab4
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: Page number for pagination
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      - name: status
        in: query
        type: string
        required: false
        description: Filter by offer status
        schema:
          type: string
          enum:
          - pending
          - accepted
          - expired
          - revoked
        example: pending
      - name: created_after
        in: query
        format: date-time
        required: false
        description: 'Filter by created_at >= this date (ISO8601). Note: uses created_at,
          not issued_at.'
        example: '2025-01-01T00:00:00Z'
        schema:
          type: string
      - name: created_before
        in: query
        format: date-time
        required: false
        description: 'Filter by created_at <= this date (ISO8601). Note: uses created_at,
          not issued_at.'
        example: '2026-12-31T23:59:59Z'
        schema:
          type: string
      - name: expires_after
        in: query
        format: date-time
        required: false
        description: Filter offers expiring after this date (ISO8601)
        example: '2027-01-01T00:00:00Z'
        schema:
          type: string
      - name: expires_before
        in: query
        format: date-time
        required: false
        description: Filter offers expiring before this date (ISO8601)
        example: '2028-12-31T23:59:59Z'
        schema:
          type: string
      - name: schema
        in: query
        required: false
        description: Filter by credential schema UUID or slug
        example: 9a06ef77-5475-4589-bff4-7d2cb0e7a16e
        schema:
          type: string
      - name: subject_identifier
        in: query
        required: false
        description: Filter by subject identifier (email or unique ID)
        example: employee@example.com
        schema:
          type: string
      - name: sort
        in: query
        type: string
        required: false
        description: Sort field
        schema:
          type: string
          enum:
          - created_at
          - expires_at
          - subject_identifier
          - status
        example: created_at
      - name: direction
        in: query
        type: string
        required: false
        description: Sort direction
        schema:
          type: string
          enum:
          - asc
          - desc
        example: desc
      responses:
        '200':
          description: List of credential offers
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CredentialOffer"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Create a credential offer
      tags:
      - Credential Offers
      description: |
        Create a new credential offer for the OpenID4VCI pre-authorized code flow.
        The offer can be shared with holders via QR code or deep link, allowing them
        to claim the credential using a compatible wallet app.
      operationId: issuer.offers.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 2f12b02b83afae43a31f735b18d14aeada59bc10aa7484a8119cc7364ec8f44a
        schema:
          type: string
      responses:
        '201':
          description: Credential offer created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialOfferResult"
        '401':
          description: Unauthorized - Invalid or missing API key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: Validation error (schema not found, invalid params)
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateOfferParams"
  "/v1/issuer/offers/{uuid}":
    get:
      summary: Get credential offer details
      tags:
      - Credential Offers
      description: |
        Retrieve details of a specific credential offer including the offer URI and deep link
        for sharing with holders.
      operationId: issuer.offers.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: ced74d63e35e8a32079e2d0316dee27ccd9cb3f40b33e088757f0d4e896a08e3
        schema:
          type: string
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential offer UUID
        example: 012d9c23-34db-46fe-b21c-feac2bd0dab8
        schema:
          type: string
      responses:
        '200':
          description: Credential offer details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialOffer"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Offer not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/offers/{uuid}/revoke":
    post:
      summary: Revoke a credential offer
      tags:
      - Credential Offers
      description: |
        Cancel an unclaimed credential offer. Only pending offers can be revoked.
        Once revoked, the offer can no longer be claimed by the holder.
      operationId: issuer.offers.revoke
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: e526f1f7ab60ae477e2a48a880bbf0374abfd81ffc4dea06e899357d3bcdeb78
        schema:
          type: string
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Credential offer UUID
        example: da52c29a-e6e7-40d4-a0aa-4a719a02f853
        schema:
          type: string
      responses:
        '200':
          description: Offer revoked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      offer:
                        "$ref": "#/components/schemas/CredentialOffer"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Offer not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: Cannot revoke non-pending offer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/schemas":
    post:
      summary: Create a credential schema
      tags:
      - Credential Schemas
      description: |
        Create a new credential schema for this issuer. Schemas define the structure
        and validation rules for credentials. New schemas are created in draft status.
      operationId: issuer.schemas.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 02303d58bc4aed06617c1c1ba5b6b5ec3f26b29c3c41f56a11bf7d74d8354ff9
        schema:
          type: string
      responses:
        '201':
          description: Schema with selective disclosure config
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/IssuerCredentialSchema"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateSchemaParams"
    get:
      summary: List issuer credential schemas
      tags:
      - Credential Schemas
      description: List all credential schemas for the authenticated issuer.
      operationId: issuer.schemas.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: e21051642ee4e8c3c5228c7d50edd7ee8cd11c5575469c8e07d399192775459d
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - draft
          - active
          - archived
        example: draft
      - name: page
        in: query
        required: false
        description: Page number
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Results per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of schemas
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/IssuerCredentialSchema"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
  "/v1/issuer/schemas/{id}":
    get:
      summary: Get credential schema details
      tags:
      - Credential Schemas
      description: Retrieve details of a specific credential schema including subject
        schema and render templates.
      operationId: issuer.schemas.get
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        required: true
        description: Schema ID
        example: gvmocyXZ0uPvaU7hYSnU
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 4b2b86f478fa0cbbef19f2ef4e786a1fa8eb71def7e6c1539cf331adc6dcbf31
        schema:
          type: string
      responses:
        '200':
          description: Schema details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/IssuerCredentialSchema"
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update a draft credential schema
      tags:
      - Credential Schemas
      description: Update a draft credential schema. Only draft schemas can be updated.
      operationId: issuer.schemas.update
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        required: true
        description: Schema ID
        example: HouBF5fNmSHG3BCKH6n6
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: c9bfecbfac59ddd9995e782b1e24c73f9b64b6a9b4cc4608585ae3662400b5fb
        schema:
          type: string
      responses:
        '200':
          description: Schema updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/IssuerCredentialSchema"
        '422':
          description: Cannot update non-draft schema
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateSchemaParams"
    delete:
      summary: Delete a draft credential schema
      tags:
      - Credential Schemas
      description: Delete a draft credential schema. Only draft schemas without credentials
        can be deleted.
      operationId: issuer.schemas.delete
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        required: true
        description: Schema ID
        example: LztS8gcRg1OWb4ujATqh
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: ee43da7f38aa06bdc9f225d29c83df99d8b58196fdbaee72a32d56169a91b384
        schema:
          type: string
      responses:
        '200':
          description: Schema deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: Cannot delete non-draft schema
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/schemas/{id}/activate":
    post:
      summary: Activate a draft credential schema
      tags:
      - Credential Schemas
      description: Activate a draft schema, making it available for credential issuance.
      operationId: issuer.schemas.activate
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        required: true
        description: Schema ID
        example: KTvHbsX4WI8MgexTdozg
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 3ba300e09db99260dfd0bc81068576835bcf3ba5a3841ba5b78b94da484175cd
        schema:
          type: string
      responses:
        '200':
          description: Schema activated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      schema:
                        "$ref": "#/components/schemas/IssuerCredentialSchema"
        '422':
          description: Cannot activate non-draft schema
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/schemas/{id}/archive":
    post:
      summary: Archive an active credential schema
      tags:
      - Credential Schemas
      description: Archive an active schema, preventing new credential issuance.
      operationId: issuer.schemas.archive
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        required: true
        description: Schema ID
        example: tI2Ur5fjPMP1yAhV97dv
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Issuer API key for authentication
        example: 89652d7daa7a72c3a39d50b0dce6727d00a971e24134df30a4d836639f7ace23
        schema:
          type: string
      responses:
        '200':
          description: Schema archived
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      schema:
                        "$ref": "#/components/schemas/IssuerCredentialSchema"
        '422':
          description: Cannot archive non-active schema
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/issuer/verify/{uuid}":
    get:
      summary: Verify a credential by UUID
      tags:
      - Credential Verification
      description: Look up and verify a credential by its UUID. Returns verification
        status and credential details.
      operationId: issuer.verify.get
      parameters:
      - name: uuid
        in: path
        format: uuid
        description: The unique identifier of the credential to verify
        example: 48bf461a-1221-4f48-b2dd-b12efbc405a6
        required: true
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: false
        description: Optional API key for verifier authentication. When provided,
          credential claims are included in the response. Without an API key, only
          verification status is returned.
        example: e92f7b75e6cc3d9a79245cd8faf47e6ac233328b58b0c84d14f24f7835a5b60e
        schema:
          type: string
      responses:
        '200':
          description: Claims included with API key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/VerificationResult"
  "/v1/issuer/verify":
    post:
      summary: Verify a credential
      tags:
      - Credential Verification
      description: |
        Verify a credential by UUID or JWT. This endpoint supports flexible verification options
        including the ability to skip specific checks (status, expiration, signature).
      operationId: issuer.verify.create
      parameters:
      - name: X-API-Key
        in: header
        required: false
        description: Optional API key for verifier authentication. When provided,
          credential claims are included in the response.
        example: 2451dfe2933e37941c45a41a8e1f4d90ee58f46103f7f803ce62c4d945747379
        schema:
          type: string
      responses:
        '200':
          description: Verification with expiration check disabled
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/VerificationResult"
        '400':
          description: Missing required parameter
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VerifyCredentialParams"
  "/v1/schemas/{schema_id}/render_templates":
    get:
      summary: List render templates
      tags:
      - Render Templates
      description: |
        List all render templates for a credential schema. Returns both custom templates
        created by the issuer and system templates. Requires issuer authentication.
      operationId: schemas.render_templates.list
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: Jd17i4ci1Ibgj2vXtbMc
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: 46ed284f53a2e4c927423ce9e9070f8f8b6146f2dc72214d9d1e886b8249153d
        schema:
          type: string
      responses:
        '200':
          description: List of templates
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/RenderTemplate"
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    post:
      summary: Create render template
      tags:
      - Render Templates
      description: |
        Create a new custom render template for a credential schema. The template content
        must be valid SVG (for svg_mustache) or HTML (for pdf_mustache). Mustache variables
        like {{name}} will be replaced with credential claims when rendering.
      operationId: schemas.render_templates.create
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: d4DhUozRnvEjtu4m391R
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: 2b78d4ca8e2dbc15dfdcbd050a265221f0dc2ec0a19da0b02ffcd25076ded7c6
        schema:
          type: string
      responses:
        '201':
          description: Template created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/RenderTemplate"
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateRenderTemplateParams"
  "/v1/schemas/{schema_id}/render_templates/{id}":
    get:
      summary: Get render template
      tags:
      - Render Templates
      description: Get details of a specific render template, including its content.
      operationId: schemas.render_templates.get
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: YbGc4gC9poOf1YJX8MQx
        schema:
          type: string
      - name: id
        in: path
        description: Render template hashid
        example: FhG9nVuDEvEj0XBtAdVn
        required: true
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: 5dfb36b6ba383324259e3d00e06573148862142d91310f679d3baf8e12728f3c
        schema:
          type: string
      responses:
        '200':
          description: Template details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/RenderTemplate"
        '404':
          description: Template not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update render template
      tags:
      - Render Templates
      description: |
        Update a custom render template. System templates cannot be modified.
        When content is updated, the digest_multibase is automatically recomputed.
      operationId: schemas.render_templates.update
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: kdEPWlpUR2uMzNapPjLR
        schema:
          type: string
      - name: id
        in: path
        description: Render template hashid
        example: P61DQuGTGR8ouBqTsD0D
        required: true
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: f07c0a30cdc5348fc2c75c6324b83f4e210e17fea33a0819bc2df7b7146b3363
        schema:
          type: string
      responses:
        '200':
          description: Template updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/RenderTemplate"
        '403':
          description: Cannot modify system template
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateRenderTemplateParams"
    delete:
      summary: Delete render template
      tags:
      - Render Templates
      description: Delete a custom render template. System templates cannot be deleted.
      operationId: schemas.render_templates.delete
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: PY9m8AzRu5SbffdA9g4E
        schema:
          type: string
      - name: id
        in: path
        description: Render template hashid
        example: mNLKA1TRjtc8LTBPC9KH
        required: true
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: 123420c5df83edac4a222eb867fcde3d1a9ad32dc4c1bedb81cdbf13760b1b35
        schema:
          type: string
      responses:
        '200':
          description: Template deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '403':
          description: Cannot delete system template
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/schemas/{schema_id}/render_templates/validate":
    post:
      summary: Validate template
      tags:
      - Render Templates
      description: |
        Validate template content without saving. Returns validation errors, warnings,
        computed digest, and extracted Mustache variables. Useful for previewing templates
        before creating them.
      operationId: schemas.render_templates.validate
      security:
      - api_key: []
      parameters:
      - name: schema_id
        in: path
        required: true
        description: Schema ID
        example: n1Mkd1swqx6YvxEfLtK8
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: API key for issuer authentication
        example: 0ab0a6ce5f01665c912eb5211c8d0198d2446612b8ecd0ad899b036cbd015f3b
        schema:
          type: string
      responses:
        '200':
          description: Validation result (invalid)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/RenderTemplateValidationResult"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ValidateRenderTemplateParams"
  "/v1/schemas":
    get:
      summary: Browse public credential schemas
      tags:
      - Schemas
      description: |
        List all available credential schemas in the public catalog. This is a public endpoint
        that does not require authentication. Supports filtering by category, tag, search query,
        and pagination.
      operationId: unauthenticated.schemas.list
      parameters:
      - name: category
        in: query
        required: false
        description: Filter schemas by category. Common categories include education,
          employment, identity, and professional.
        example: education
        schema:
          type: string
      - name: tag
        in: query
        required: false
        description: Filter schemas by tag. Tags are keywords associated with schemas
          for easier discovery.
        example: degree
        schema:
          type: string
      - name: q
        in: query
        required: false
        description: Search query to filter schemas by name or description. Performs
          a case-insensitive partial match.
        example: university
        schema:
          type: string
      - name: page
        in: query
        required: false
        description: 'Page number for pagination (default: 1)'
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Items per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: Filtered by category
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CredentialSchema"
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      per_page:
                        type: integer
                      total_count:
                        type: integer
                      total_pages:
                        type: integer
                      categories:
                        type: array
                        items:
                          type: string
                        description: Available categories for filtering
                      tags:
                        type: object
                        additionalProperties:
                          type: integer
                        description: Available tags with counts
  "/v1/schemas/{slug}":
    get:
      summary: Get schema details
      tags:
      - Schemas
      description: |
        Get detailed information about a specific credential schema by its slug.
        Includes the full schema definition, claim fields, and related schemas.
      operationId: unauthenticated.schemas.get
      parameters:
      - name: slug
        in: path
        description: Schema slug (URL-friendly identifier)
        example: university-diploma
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Schema details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/CredentialSchema"
                  meta:
                    type: object
                    properties:
                      related_schemas:
                        type: array
                        items:
                          "$ref": "#/components/schemas/CredentialSchema"
                        description: Other schemas in the same category
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/dc_sessions":
    post:
      summary: Create a DC API session
      tags:
      - DC API Sessions
      description: |
        Create a new Digital Credentials API session for server-to-server verification.

        Returns encryption keys and request configurations for both Chrome/Android (OpenID4VP)
        and Safari/iOS (mdoc) protocols. Your frontend uses these to call navigator.credentials.get()
        and then POSTs the encrypted response back to the verify endpoint.

        **Requires Secret Key authentication** (`aho_sec-*` format API key).
      operationId: verifier.dc_sessions.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Secret API key for authentication (aho_sec-* format)
        example: aho_sec-abe161d7-917b-44ad-b61f-cdeee3511e6a
        schema:
          type: string
      responses:
        '201':
          description: Session created
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DcApiSessionCreateResponse"
        '401':
          description: Unauthorized - publishable key not allowed
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '403':
          description: Forbidden - IP not in allowed list
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateDcSessionParams"
  "/v1/verifier/dc_sessions/{id}":
    get:
      summary: Get DC API session status
      tags:
      - DC API Sessions
      description: |
        Retrieve the status and results of a DC API session.

        This is the key endpoint for secure backend confirmation. After verification
        completes, poll this endpoint from your backend to get the verified claims.
        Never trust claims sent from the frontend - always confirm via this endpoint.

        **Requires Secret Key authentication** from the same account that created the session.
      operationId: verifier.dc_sessions.get
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        format: uuid
        required: true
        description: Session UUID
        example: 63be440b-1c5b-4337-8fad-48c19876e037
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Secret API key for authentication
        example: aho_sec-42f28842-d78d-4647-b641-945e61288cca
        schema:
          type: string
      responses:
        '200':
          description: Session status (completed)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/DcApiSession"
        '404':
          description: Session belongs to different account
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/dc_sessions/{id}/verify":
    post:
      summary: Verify a DC API session
      tags:
      - DC API Sessions
      description: |
        Verify a DC API session with the wallet's encrypted response.

        Call this after your frontend receives the response from navigator.credentials.get().
        The response is decrypted and validated server-side. On success, returns the
        verified claims and issuer information.

        This endpoint is **idempotent** - if the session is already completed, it returns
        the cached result.

        **Requires Secret Key authentication**.
      operationId: verifier.dc_sessions.verify
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        format: uuid
        required: true
        description: Session UUID
        example: 3f79f4be-6ed5-46ba-8d27-1a3eae435fe0
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Secret API key for authentication
        example: aho_sec-1e1e15b6-8488-46c7-9c87-b771b2116934
        schema:
          type: string
      responses:
        '200':
          description: Cached result for completed session (idempotent)
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DcApiSessionVerifyResponse"
        '409':
          description: Session already failed
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: Verification failed
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VerifyDcSessionParams"
  "/v1/verifier/dc_sessions/{id}/render":
    get:
      summary: Render verified claims as visual credential
      tags:
      - DC API Sessions
      description: |
        Render verified claims from a completed session as an SVG, PDF, or HTML credential card.

        This endpoint provides a visual representation of the verified credential, suitable
        for display in admin interfaces or user-facing confirmation screens.

        **Requires Secret Key authentication** from the same account that created the session.
        The session must be completed with verified claims.
      operationId: verifier.render.list
      security:
      - api_key: []
      parameters:
      - name: id
        in: path
        format: uuid
        required: true
        description: Session UUID
        example: 0e11a6c3-f76e-482f-b43a-6db7dccd98ba
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Secret API key for authentication
        example: aho_sec-1acfd5ad-411d-4108-8446-922fef087646
        schema:
          type: string
      - name: format
        in: query
        required: false
        description: "Output format (svg, pdf, html). Defaults to svg.:\n * `svg`
          \n * `pdf` \n * `html` \n "
        enum:
        - svg
        - pdf
        - html
        example: svg
        schema:
          type: string
      responses:
        '200':
          description: Rendered credential (HTML)
        '400':
          description: Session has no verified claims
          content:
            image/svg+xml:
              schema:
                "$ref": "#/components/schemas/Error"
            application/pdf:
              schema:
                "$ref": "#/components/schemas/Error"
            text/html:
              schema:
                "$ref": "#/components/schemas/Error"
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Session belongs to different account
          content:
            image/svg+xml:
              schema:
                "$ref": "#/components/schemas/Error"
            application/pdf:
              schema:
                "$ref": "#/components/schemas/Error"
            text/html:
              schema:
                "$ref": "#/components/schemas/Error"
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized - invalid API key
          content:
            image/svg+xml:
              schema:
                "$ref": "#/components/schemas/Error"
            application/pdf:
              schema:
                "$ref": "#/components/schemas/Error"
            text/html:
              schema:
                "$ref": "#/components/schemas/Error"
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/render":
    post:
      summary: Render claims as visual credential
      tags:
      - Credential Rendering
      description: |
        Render claims as a visual credential card (SVG, PDF, or HTML).

        Accepts either a built-in template key or a W3C renderMethod with claims.
        Returns the rendered content along with template verification status.

        **Requires Secret Key authentication** (`aho_sec-*` format API key).
      operationId: verifier.render.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Secret API key for authentication
        example: aho_sec-f8de5c24-0c55-4e82-9e5d-cee4fff2b2c0
        schema:
          type: string
      responses:
        '200':
          description: Rendered with W3C renderMethod
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/RenderResponse"
        '422':
          description: Missing claims
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '401':
          description: Unauthorized - publishable key not allowed
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RenderParams"
  "/v1/verifier/requests":
    post:
      summary: Create a presentation request
      tags:
      - Presentation Requests
      description: |
        Create a new OpenID4VP presentation request. The request defines what credentials
        and claims the verifier wants from a holder. Supports both Presentation Exchange
        and DCQL query formats.
      operationId: verifier.requests.create
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 0fc8f7a8bdea6e447ec3f2a987b33e79eb46fe350f894ac61836c84e79f6635e
        schema:
          type: string
      responses:
        '201':
          description: Presentation request created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/PresentationRequest"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreatePresentationRequestParams"
    get:
      summary: List presentation requests
      tags:
      - Presentation Requests
      description: List all presentation requests for the authenticated verifier.
      operationId: verifier.requests.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 74833a3dfec1adc2e95070a15182c2656cd4347f4f7433172c6ab97924e36803
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by status
        schema:
          type: string
          enum:
          - draft
          - active
          - expired
          - closed
        example: draft
      - name: page
        in: query
        required: false
        description: Page number
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Results per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of requests
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/PresentationRequest"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{uuid}":
    get:
      summary: Get presentation request details
      tags:
      - Presentation Requests
      description: Retrieve details of a specific presentation request including URLs
        and response stats.
      operationId: verifier.requests.get
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: 2d429533-5872-4f82-b5b8-402c46a8220e
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 183d2effebe8d9bdfed246f67924a24f2ea70f12d99661ec6ac4cfbd94781455
        schema:
          type: string
      responses:
        '200':
          description: Request details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/PresentationRequest"
        '404':
          description: Request not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
    patch:
      summary: Update a draft presentation request
      tags:
      - Presentation Requests
      description: Update a draft presentation request. Only draft requests can be
        updated.
      operationId: verifier.requests.update
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: d81dbd1e-f57b-4735-9fe0-6f64098b8df0
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: a601b33d9d6690ae530b09fdbd6473c0ec5487d770995c422d50ba27e1e52247
        schema:
          type: string
      responses:
        '200':
          description: Request updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/PresentationRequest"
        '422':
          description: Cannot update non-draft request
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdatePresentationRequestParams"
    delete:
      summary: Delete a draft presentation request
      tags:
      - Presentation Requests
      description: Delete a draft presentation request. Only draft requests can be
        deleted.
      operationId: verifier.requests.delete
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: a8f74ce9-6baf-45ef-afe7-5485c028faa8
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: a1a7ace12e5acdc9b5bd06a3104bf02527103e93e3e951c458a7c6a2effc27c2
        schema:
          type: string
      responses:
        '200':
          description: Request deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
        '422':
          description: Cannot delete non-draft request
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{uuid}/activate":
    post:
      summary: Activate a draft presentation request
      tags:
      - Presentation Requests
      description: Activate a draft request, making it available for holders to respond
        to.
      operationId: verifier.requests.activate
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: b25a40d2-65b3-4fb3-a80f-6e518d73f00d
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 317d8a37576b44eb0cf3b0344b7ebaffb7cb4ea6ffa44dfd39872bb3f3c0db37
        schema:
          type: string
      responses:
        '200':
          description: Request activated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      request:
                        "$ref": "#/components/schemas/PresentationRequest"
        '422':
          description: Cannot activate non-draft request
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{uuid}/close":
    post:
      summary: Close an active presentation request
      tags:
      - Presentation Requests
      description: Close an active request, preventing any more responses.
      operationId: verifier.requests.close
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: 726d58f2-50c6-4fcb-9dee-7e8b7eb7d64e
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: f6222d723b9bbdcca21c5cde05478d1906d74204bd610e355397f4aa4efb48fd
        schema:
          type: string
      responses:
        '200':
          description: Request closed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      request:
                        "$ref": "#/components/schemas/PresentationRequest"
        '422':
          description: Cannot close non-active request
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{uuid}/qr_code":
    get:
      summary: Get QR code for presentation request
      tags:
      - Presentation Requests
      description: |
        Generate a QR code for the presentation request. The QR code contains the OpenID4VP URI
        that wallets can scan to respond to the request. Only available for active requests.
      operationId: verifier.requests.qr_code
      security:
      - api_key: []
      parameters:
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: '097a5533-882b-4640-a95c-aac90a3ee88e'
        schema:
          type: string
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 31f9401e3973de9212b9ea1688d8c4c6b508126aea552ffcc67997cbc21c5afd
        schema:
          type: string
      - name: format
        in: query
        type: string
        required: false
        description: Output format
        schema:
          type: string
          enum:
          - svg
          - png
          - base64
        example: svg
      responses:
        '200':
          description: QR code (base64 JSON)
          content:
            image/svg+xml:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      format:
                        type: string
                        example: base64
                      data:
                        type: string
                        description: Base64-encoded PNG
                      content_type:
                        type: string
                        example: image/png
                      openid4vp_uri:
                        type: string
                        description: The encoded URI
            image/png:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      format:
                        type: string
                        example: base64
                      data:
                        type: string
                        description: Base64-encoded PNG
                      content_type:
                        type: string
                        example: image/png
                      openid4vp_uri:
                        type: string
                        description: The encoded URI
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      format:
                        type: string
                        example: base64
                      data:
                        type: string
                        description: Base64-encoded PNG
                      content_type:
                        type: string
                        example: image/png
                      openid4vp_uri:
                        type: string
                        description: The encoded URI
        '422':
          description: QR code not available for draft request
          content:
            image/svg+xml:
              schema:
                "$ref": "#/components/schemas/Error"
            image/png:
              schema:
                "$ref": "#/components/schemas/Error"
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{request_uuid}/responses":
    get:
      summary: List responses for a presentation request
      tags:
      - Presentation Responses
      description: |
        List all responses received for a specific presentation request.
        Responses include holder-disclosed claims and verification status.
      operationId: verifier.responses.list
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 2a902e25b9472abb5ac18dc8023ebe7aa938615a7de529f087f17b3b149ead37
        schema:
          type: string
      - name: request_uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: 8db108d2-bb2a-4096-b3ec-1ffc9a24768b
        schema:
          type: string
      - name: status
        in: query
        type: string
        required: false
        description: Filter by response status
        schema:
          type: string
          enum:
          - pending
          - approved
          - declined
        example: pending
      - name: page
        in: query
        required: false
        description: Page number
        example: 1
        schema:
          type: integer
      - name: per_page
        in: query
        required: false
        description: 'Results per page (default: 25, max: 100)'
        example: 25
        schema:
          type: integer
      responses:
        '200':
          description: List of responses
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/PresentationResponse"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
        '404':
          description: Presentation request not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
  "/v1/verifier/requests/{request_uuid}/responses/{uuid}":
    get:
      summary: Get response details
      tags:
      - Presentation Responses
      description: |
        Retrieve detailed information about a specific presentation response,
        including all disclosed claims and credential information.
      operationId: verifier.responses.get
      security:
      - api_key: []
      parameters:
      - name: X-API-Key
        in: header
        required: true
        description: Verifier API key for authentication
        example: 76f53cd2531511c3efc145044d261fa7c8b010067798d8fef49073e666d0db24
        schema:
          type: string
      - name: request_uuid
        in: path
        format: uuid
        required: true
        description: Presentation request UUID
        example: 79947d52-f3ec-4d4a-ace6-09746d8ca51d
        schema:
          type: string
      - name: uuid
        in: path
        format: uuid
        required: true
        description: Response UUID
        example: 14cd5b74-6c48-4370-9da2-232107caae85
        schema:
          type: string
      responses:
        '200':
          description: Response details
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    "$ref": "#/components/schemas/PresentationResponse"
        '404':
          description: Response not found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Error"
servers:
- url: "{protocol}://{host}"
  variables:
    protocol:
      default: https
      enum:
      - http
      - https
    host:
      default: api.aho.com
tags:
- name: Credential Schemas
  x-icon: credential_schema
  description: |-
    **Credential Schemas** define the structure and validation rules for your verifiable credentials.

    A schema specifies:
    - The credential type (e.g., "EmployeeBadgeCredential")
    - The claims/fields the credential contains (name, title, department, etc.)
    - Validation rules for each field (required, format, allowed values)
    - Supported credential formats (JWT-VC, SD-JWT-VC, mdoc)

    **Workflow:** Create a schema first, then use it when issuing credentials or setting up automations.
    New schemas start in "draft" status and must be activated before use.
- name: Data Sources
  x-icon: data_source
  description: |-
    **Data Sources** connect to external systems that contain subject data for automated credential issuance.

    Supported source types:
    - **PostgreSQL**: Connect to a database to query employee/student/member records
    - **CSV**: Upload files for batch processing

    Data sources store encrypted connection credentials and can be tested before activation.
    Use data sources with Data Source Mappings and Automations to issue credentials automatically.
- name: Data Source Mappings
  x-icon: data_source_mapping
  description: |-
    **Data Source Mappings** define how data from a source translates into credential claims.

    A mapping connects:
    - A **Data Source** (where to get the data)
    - A **Credential Schema** (what credential to issue)
    - **Field Mappings** (which source columns map to which credential claims)
    - **Query Configuration** (how to extract records from the source)

    Example: Map the "full_name" database column to the "name" credential claim.
- name: Automations
  x-icon: credential_automation
  description: |-
    **Automations** run credential issuance workflows automatically based on triggers.

    Trigger modes:
    - **Manual**: Triggered via API call or dashboard button
    - **Scheduled**: Runs on a cron schedule (e.g., daily at midnight)
    - **Webhook**: Triggered by external systems via webhook URL

    Each automation uses a Data Source Mapping to know what data to fetch and what credentials to issue.
    Automations can be paused, resumed, and monitored for run history.
- name: Credential Issuances
  x-icon: credential
  description: |-
    **Credentials** are the verifiable credentials you issue to holders.

    Operations:
    - Issue new credentials (directly or via credential offers)
    - List and search issued credentials
    - Revoke or suspend credentials
    - Check credential status

    Credentials are cryptographically signed using your signing keys and can be verified by anyone.
- name: Credential Offers
  x-icon: credential_offer
  description: |-
    **Credential Offers** let holders claim credentials through a wallet app using OpenID4VCI protocol.

    Flow:
    1. Create an offer with the credential data
    2. Share the offer URL or QR code with the holder
    3. Holder scans/clicks and their wallet fetches the credential

    Offers can be one-time use or reusable, with optional PIN protection.
- name: Credential Verification
  x-icon: credential_verification
  description: |-
    **Verification** validates credentials and checks their authenticity.

    Verification checks:
    - Cryptographic signature validity
    - Expiration status
    - Revocation/suspension status
    - Issuer trust signals (domain verification, organization info)

    Use this to verify credentials presented to you before trusting their claims.
- name: Presentation Requests
  x-icon: presentation_request
  description: |-
    **Presentation Requests** ask holders to present specific credentials using OpenID4VP protocol.

    Define what credentials you need:
    - Required credential types
    - Required claims within those credentials
    - Optional constraints (issuer, expiration, etc.)

    Requests generate a URL/QR code that holders scan to share matching credentials from their wallet.
- name: Presentation Responses
  x-icon: presentation_response
  description: |-
    **Presentation Responses** contain the credentials holders submit in response to your requests.

    After a holder responds to a presentation request, retrieve and verify the submitted credentials here.
    Responses include the raw credential data and verification status.
- name: DC API Sessions
  x-icon: dc_api_session
  description: |-
    **DC API Sessions** enable server-to-server verification using the Digital Credentials API.

    The thin client architecture keeps credential handling server-side:
    1. Create a session to get encryption keys and request configs
    2. Your frontend uses the Digital Credentials API to request credentials
    3. POST the encrypted response back to verify and extract claims

    Benefits:
    - No credential data exposed to frontend JavaScript
    - Cryptographic binding via session transcript
    - Works with Chrome/Android (OpenID4VP) and Safari/iOS (mdoc)

    Sessions expire after 5 minutes and are single-use.
- name: Credentials
  x-icon: credential
  description: |-
    **Holder Credentials** are credentials owned by an end user (holder).

    Operations:
    - List credentials in the holder's wallet
    - View credential details and claims
    - Delete credentials from the wallet

    Holders receive credentials through credential offers or direct issuance.
- name: Presentations
  x-icon: credential_presentation
  description: |-
    **Presentations** are packaged credentials that holders share with verifiers.

    Create verifiable presentations to respond to verification requests,
    proving you hold certain credentials without revealing unnecessary information.
- name: Domains
  x-icon: account_domain
  description: |-
    **Custom Domains** establish your organization's identity for credential issuance.

    Your domain becomes part of your DID (Decentralized Identifier): `did:web:yourdomain.com`

    Domain verification:
    1. Add your domain
    2. Create the required DNS TXT record
    3. Verify ownership

    A verified domain increases trust in your issued credentials.
- name: Signing Keys
  x-icon: signing_key
  description: |-
    **Signing Keys** are the cryptographic keys used to sign your verifiable credentials.

    Key features:
    - Keys are generated and stored securely (never exposed)
    - Support for key rotation with overlap periods
    - Multiple algorithms supported (ES256, EdDSA)

    Each credential is signed with your active key, allowing verifiers to confirm authenticity.
- name: API Keys
  x-icon: api_key
  description: |-
    **API Keys** authenticate your API requests.

    Each account has two types of keys:
    - **Secret Key**: For server-to-server API calls. Never expose in client-side code.
    - **Publishable Key**: For browser-based requests. Restricted by origin allowlist.

    Keys auto-create on first access and can be regenerated if compromised (old value stops working immediately).
- name: Webhooks
  x-icon: webhook
  description: |-
    **Webhooks** notify your systems when events occur in your account.

    Supported events:
    - Credential issued, revoked, suspended
    - Presentation request completed
    - Domain verification status changes

    Configure a webhook URL to receive real-time event notifications with cryptographic signatures for verification.
- name: Hooks
  x-icon: webhook
  description: |-
    **Webhook Triggers** allow external systems to trigger actions without API key authentication.

    Currently supports:
    - **Automation triggers**: External systems POST to trigger credential automation runs

    Each trigger uses a unique token URL. Tokens can be regenerated if compromised.
- name: Schemas
  x-icon: credential_schema
  description: |-
    **Public Schema Registry** provides read-only access to credential schemas.

    Anyone can browse available credential types and their claim structures.
    No authentication required.
- name: Render Templates
  x-icon: render_template
  description: |-
    **Render Templates** define how credentials are visually displayed.

    Templates use Liquid syntax to generate SVG or HTML representations
    of credentials for display in wallets, emails, or print.
- name: System
  x-icon: health
  description: Health check and system status endpoints.
x-tagGroups:
- name: Issuer
  tags:
  - Credential Schemas
  - Credential Issuances
  - Credential Offers
  - Automations
  - Data Sources
  - Data Source Mappings
  - Render Templates
- name: Verifier
  tags:
  - Credential Verification
  - Presentation Requests
  - Presentation Responses
  - DC API Sessions
- name: Holder
  tags:
  - Credentials
  - Presentations
- name: Account
  tags:
  - Domains
  - Signing Keys
  - API Keys
  - Webhooks
- name: Public
  tags:
  - Schemas
  - System
- name: Integrations
  tags:
  - Hooks
components:
  securitySchemes:
    api_key:
      type: apiKey
      name: X-API-Key
      in: header
      description: |-
        API key for issuer/verifier authentication.
        - Issuers: Get your key from Issuer Dashboard > Settings > API Key
        - Verifiers: Get your key from Verifier Dashboard > Settings > API Key
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: Base64
      description: |-
        Bearer token for holder authentication.
        Used for creating and managing credential presentations.
        Token format: Base64-encoded account ID.
  schemas:
    VerificationResult:
      type: object
      description: |-
        Verification response with standard envelope. Contains:
        - success: Whether the API call succeeded
        - data: Object with verified (bool), status (string), message, verified_at, credential details
      properties:
        success:
          type: boolean
          description: Whether the API call succeeded
          example: true
        data:
          type: object
          description: Verification result data
          properties:
            verified:
              type: boolean
              description: Whether the credential is valid
              example: true
            status:
              type: string
              enum:
              - success
              - not_found
              - invalid_signature
              - expired
              - revoked
              - suspended
              - malformed
              example: success
              description: |-
                Detailed verification result code:
                - success: Credential is valid and all checks passed
                - not_found: No credential exists with the given identifier
                - invalid_signature: Cryptographic signature verification failed
                - expired: Credential has passed its expiration date
                - revoked: Credential was permanently invalidated by the issuer
                - suspended: Credential is temporarily disabled
                - malformed: Credential format is invalid or corrupted
            message:
              type: string
              description: Human-readable verification message
              example: Credential verified successfully
            verified_at:
              type: string
              format: date-time
              description: When verification was performed
              example: '2025-01-15T10:30:00Z'
            trust_path:
              type: string
              description: Trust verification path used
              example: did:web
            error:
              type: string
              nullable: true
              description: Error message if verification failed
              example:
            trust:
              type: object
              nullable: true
              description: Trust information for the issuer
              properties:
                verdict:
                  type: string
                  description: Trust verdict
                  example: trusted
                score:
                  type: number
                  description: Trust score
                  example: 85.0
                source_type:
                  type: string
                  description: Source of trust information
                  example: did:web
                domain:
                  type: string
                  nullable: true
                  description: Issuer domain
                  example: acme-corp.com
                domain_fully_verified:
                  type: boolean
                  description: Whether domain is fully verified
                  example: true
                signals:
                  type: array
                  items:
                    type: object
                    properties:
                      icon:
                        type: string
                        description: Visual indicator character
                        example: "✓"
                      text:
                        type: string
                        description: Signal description
                        example: Domain ownership verified
                      status:
                        type: string
                        enum:
                        - success
                        - danger
                        - neutral
                        description: Signal status level
                        example: success
                  description: Trust signals with status indicators
                warnings:
                  type: array
                  items:
                    type: string
                  description: Trust warnings
                  example: []
            credential:
              type: object
              nullable: true
              description: Credential details (only present when credential is found)
              properties:
                uuid:
                  type: string
                  format: uuid
                  example: f74aeab4-8a6c-408f-b52b-58112bd18183
                status:
                  type: string
                  example: active
                type:
                  type: string
                  description: Credential type
                  example: EmployeeBadgeCredential
                type_display:
                  type: string
                  description: Human-readable credential type
                  example: Employee Badge
                schema:
                  type: object
                  nullable: true
                  properties:
                    uuid:
                      type: string
                      format: uuid
                      example: e6cac86d-df2e-430f-bb62-f416218eabdb
                    name:
                      type: string
                      example: Employee Badge Schema
                issuer:
                  type: object
                  properties:
                    name:
                      type: string
                      example: Acme Corporation
                    did:
                      type: string
                      example: did:web:acme-corp.com
                    domain:
                      type: string
                      nullable: true
                      example: acme-corp.com
                    domain_fully_verified:
                      type: boolean
                      example: true
                subject:
                  type: object
                  properties:
                    identifier_type:
                      type: string
                      nullable: true
                      example: email
                    did:
                      type: string
                      nullable: true
                      example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
                issued_at:
                  type: string
                  format: date-time
                  example: '2025-01-01T00:00:00Z'
                expires_at:
                  type: string
                  format: date-time
                  nullable: true
                  example: '2027-01-01T00:00:00Z'
                claims:
                  type: object
                  additionalProperties: true
                  nullable: true
                  description: Credential claims (only when authenticated)
                  example:
                    name: Jane Smith
                    title: Software Engineer
                    department: Engineering
          required:
          - verified
          - status
      required:
      - success
      - data
    PresentationVerifyResult:
      type: object
      description: |-
        Response from verifying a holder's selective disclosure presentation.
        Contains verification status, disclosed claims, and credential/presentation metadata.
      properties:
        success:
          type: boolean
          description: Whether the API call succeeded
          example: true
        data:
          type: object
          description: Verification result data
          properties:
            verified:
              type: boolean
              description: Whether the presentation is valid
              example: true
            error:
              type: string
              nullable: true
              description: Error message if verification failed
              example:
            disclosed_claims:
              type: object
              additionalProperties: true
              nullable: true
              description: The claims disclosed in this presentation (dynamic, schema-dependent)
              example:
                name: Jane Smith
                over_21: true
            credential:
              type: object
              nullable: true
              description: Source credential information
              properties:
                uuid:
                  type: string
                  format: uuid
                  example: a373791a-3acd-410a-b236-d314ea4f0b8b
                schema:
                  type: string
                  example: AgeVerificationCredential
                issuer:
                  type: object
                  properties:
                    name:
                      type: string
                      example: State DMV
                    did:
                      type: string
                      example: did:web:dmv.state.gov
                issued_at:
                  type: string
                  format: date-time
                  example: '2025-01-01T00:00:00Z'
                expires_at:
                  type: string
                  format: date-time
                  nullable: true
                  example: '2030-01-01T00:00:00Z'
            presentation:
              type: object
              nullable: true
              description: Presentation metadata
              properties:
                uuid:
                  type: string
                  format: uuid
                  example: 7b676070-3e1d-409e-aaeb-8978b3edeace
                created_at:
                  type: string
                  format: date-time
                  example: '2025-03-15T14:30:00Z'
                expires_at:
                  type: string
                  format: date-time
                  nullable: true
                  example: '2027-03-15T15:30:00Z'
                verification_count:
                  type: integer
                  example: 1
          required:
          - verified
      required:
      - success
      - data
    IssuerRefWithTrust:
      type: object
      description: Issuer reference including trust verification indicators
      properties:
        did:
          type: string
          example: did:web:stanford.edu
        name:
          type: string
          example: Stanford University
        trust:
          "$ref": "#/components/schemas/TrustMeta"
      required:
      - did
      - name
    TrustMeta:
      type: object
      description: Trust verification metadata for an organization
      properties:
        level:
          type: string
          enum:
          - unverified
          - email_verified
          - domain_fully_verified
          description: |-
            Overall trust level based on completed verifications:
            - unverified: No verification completed
            - email_verified: Organization email matches their claimed domain
            - domain_fully_verified: Domain ownership proven via DNS TXT record / well-known file and CNAME entry
          example: domain_fully_verified
        email_verified:
          type: boolean
          description: Whether the organization email matches their claimed domain
          example: true
        domain_fully_verified:
          type: boolean
          description: Whether domain ownership was verified (via DNS TXT record or
            /.well-known/aho-verification.json file and CNAME entry)
          example: true
        domain_verified_at:
          type: string
          format: date-time
          nullable: true
          description: When domain verification was completed (null if not yet verified)
          example: '2025-01-10T09:00:00Z'
        domain_rank:
          type: integer
          nullable: true
          description: Domain ranking based on analyzed traffic data (1 = most popular)
          example: 523
        domain_rank_display:
          type: string
          enum:
          - Top 100 website
          - Top 1K website
          - Top 10K website
          - Top 100K website
          - Known website
          - Unknown website
          description: |-
            Human-readable domain ranking tier based on analyzed traffic data:
            - Top 100/1K/10K/100K website: Domain ranks in that tier globally
            - Known website: Domain is ranked but outside top 100K
            - Unknown website: Domain not found in ranking data
          example: Top 1K website
        typosquatting_warning:
          "$ref": "#/components/schemas/TyposquattingWarning"
          nullable: true
      required:
      - level
      - email_verified
      - domain_fully_verified
      - domain_rank_display
    TyposquattingWarning:
      type: object
      nullable: true
      description: Present if the domain resembles a well-known domain
      properties:
        similar_to:
          type: string
          description: The well-known domain this resembles
          example: google.com
        similar_to_rank:
          type: string
          description: Ranking tier of the similar domain
          example: Top 10 website
      required:
      - similar_to
      - similar_to_rank
    IssuerRef:
      type: object
      description: Issuer reference with optional domain verification status
      properties:
        name:
          type: string
          description: Organization name
          example: Stanford University
        did:
          type: string
          pattern: "^did:[a-z]+:.+"
          description: Decentralized Identifier
          example: did:web:stanford.edu
        domain:
          type: string
          nullable: true
          description: Issuer's verified domain
          example: stanford.edu
        domain_fully_verified:
          type: boolean
          description: Whether the issuer's domain is fully verified
          example: true
    SchemaRef:
      type: object
      description: Credential schema reference
      nullable: true
      properties:
        uuid:
          type: string
          format: uuid
          description: Schema UUID
          example: 28b9daa3-94b9-40fe-ab1b-a4315de20afc
        name:
          type: string
          description: Schema display name
          example: University Degree
        type:
          type: string
          description: Credential type identifier
          example: UniversityDegreeCredential
        slug:
          type: string
          description: URL-friendly schema identifier
          example: university-degree
    SubjectRef:
      type: object
      description: Credential subject identification
      properties:
        identifier_type:
          type: string
          nullable: true
          description: Type of identifier (email, did)
          example: email
        did:
          type: string
          nullable: true
          description: Subject's Decentralized Identifier
          example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
    SigningKeyRef:
      type: object
      description: Reference to the signing key used for a credential
      nullable: true
      properties:
        id:
          type: string
          description: Signing key identifier
          example: key-043b1dc6-863a-4b4a-8eed-2167ae85aaf9
        key_id:
          type: string
          description: Key ID used in JWT header (kid)
          example: did:web:acme-corp.com#key-1
        algorithm:
          type: string
          enum:
          - es256
          - es384
          - ed25519
          description: Signing algorithm
          example: ed25519
    TrustSignal:
      type: object
      description: A trust verification signal with status indicator
      properties:
        icon:
          type: string
          description: Visual indicator character
          example: "✓"
        text:
          type: string
          description: Signal description
          example: Domain ownership verified
        status:
          type: string
          enum:
          - success
          - danger
          - neutral
          description: Signal status level
          example: success
    PaginationMeta:
      type: object
      description: Pagination metadata for list responses
      properties:
        current_page:
          type: integer
          minimum: 1
          description: Current page number
          example: 1
        per_page:
          type: integer
          minimum: 1
          maximum: 100
          description: Items per page
          example: 25
        total_count:
          type: integer
          minimum: 0
          description: Total number of items
          example: 42
        total_pages:
          type: integer
          minimum: 0
          description: Total number of pages
          example: 2
      required:
      - current_page
      - per_page
      - total_count
      - total_pages
    FieldError:
      type: object
      description: Structured field-level validation error
      properties:
        field:
          type: string
          description: JSON path to the invalid field
          example: claims.degree
        issue:
          type: string
          description: Machine-readable error type
          enum:
          - type_mismatch
          - missing_required
          - invalid_enum
          - pattern_mismatch
          - length_violation
          - range_violation
          - format_invalid
          - array_size_violation
          - duplicate_items
          - unexpected_property
          - validation_failed
          example: type_mismatch
        expected:
          type: string
          nullable: true
          description: Expected value/type
          example: string
        got:
          type: string
          nullable: true
          description: Actual value/type received
          example: '123'
        hint:
          type: string
          nullable: true
          description: Human-readable fix suggestion
          example: The 'degree' field must be a string
      required:
      - field
      - issue
    Error:
      type: object
      description: Standard error response envelope
      properties:
        success:
          type: boolean
          description: Always false for errors
          example: false
        error:
          type: object
          description: Error details
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: not_found
            message:
              type: string
              description: Human-readable error message
              example: Resource not found.
            details:
              description: Additional context - string, array of strings, or array
                of field errors
              nullable: true
              oneOf:
              - type: string
              - type: array
                items:
                  type: string
              - type: array
                items:
                  "$ref": "#/components/schemas/FieldError"
          required:
          - code
          - message
        retry_after:
          type: integer
          nullable: true
          description: Seconds to wait before retrying (for rate limit errors)
          example: 30
      required:
      - success
      - error
    RateLimitError:
      type: object
      description: Rate limit exceeded error response (HTTP 429)
      properties:
        success:
          type: boolean
          description: Always false
          example: false
        error:
          type: object
          properties:
            code:
              type: string
              description: Error code
              example: rate_limit_exceeded
            message:
              type: string
              description: Error message
              example: Rate limit exceeded. Please wait before retrying.
          required:
          - code
          - message
        retry_after:
          type: integer
          description: Seconds to wait before retrying
          example: 60
      required:
      - success
      - error
      - retry_after
    Credential:
      type: object
      description: A verifiable credential issued to a holder
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the credential
          example: 956d85a8-d584-4566-9ed3-e6b87ffd57fc
        status:
          type: string
          enum:
          - active
          - suspended
          - revoked
          - expired
          - archived
          example: active
          description: |-
            Current status of the credential:
            - active: Credential is valid and can be verified
            - suspended: Temporarily disabled, can be reactivated
            - revoked: Permanently invalidated, cannot be restored
            - expired: Credential has passed its expiration date
            - archived: Credential has been archived by the holder
        subject_identifier:
          type: string
          description: Email or DID identifying the credential subject
          example: student@university.edu
        subject_identifier_type:
          type: string
          enum:
          - email
          - did
          example: email
          description: |-
            Type of identifier used for the subject:
            - email: Standard email address
            - did: Decentralized Identifier (e.g., did:web:example.com)
        issued_at:
          type: string
          format: date-time
          description: When the credential was issued
          example: '2025-01-15T10:00:00Z'
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the credential expires (null if no expiration)
          example: '2027-01-15T10:00:00Z'
        created_at:
          type: string
          format: date-time
          description: When the credential record was created
          example: '2025-01-15T10:00:00Z'
        schema:
          type: object
          nullable: true
          description: The credential schema this credential is based on
          properties:
            uuid:
              type: string
              format: uuid
              description: Unique identifier for the schema
              example: 15a136e7-e248-4598-b548-960d737f2ef7
            name:
              type: string
              minLength: 1
              description: Human-readable schema name
              example: University Degree
            type:
              type: string
              minLength: 1
              description: Credential type identifier used in the JWT
              example: UniversityDegreeCredential
            slug:
              type: string
              description: URL-friendly schema identifier
              example: university-degree
        issuer:
          type: object
          description: The organization that issued this credential
          properties:
            name:
              type: string
              minLength: 1
              description: Organization name
              example: Stanford University
            did:
              type: string
              pattern: "^did:[a-z]+:.+"
              description: Decentralized Identifier for the issuer
              example: did:web:stanford.edu
            domain:
              type: string
              nullable: true
              description: Issuer's verified domain
              example: stanford.edu
            domain_fully_verified:
              type: boolean
              description: Whether the issuer's domain is fully verified
              example: true
        verification_url:
          type: string
          format: uri
          description: URL where this credential can be verified
          example: https://aho.com/verify/d31888ee-141d-4ed5-aead-8cb0ceb7970f
        credential_jwt:
          type: string
          nullable: true
          description: The signed JWT credential token (null if not yet generated)
          example: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
        claims:
          type: object
          additionalProperties: true
          nullable: true
          description: The credential claims/attributes (dynamic, schema-dependent)
          example:
            name: Jane Doe
            degree: Bachelor of Science
            major: Computer Science
        subject_id:
          type: string
          nullable: true
          description: Internal subject identifier
          example: did:web:example.com:users:12345
        vc_json:
          type: object
          additionalProperties: true
          nullable: true
          description: Raw VC JSON-LD document (only present for some credential types)
        issuer_signing_key:
          type: object
          nullable: true
          description: Information about the signing key used
          properties:
            id:
              type: string
              description: Signing key identifier
              example: key-bf83896c-d0a5-4364-bef4-9dd6f13bb0c2
            key_id:
              type: string
              description: Key ID used in JWT header
              example: did:web:stanford.edu#key-1
            algorithm:
              type: string
              enum:
              - es256
              - es384
              - ed25519
              description: Signing algorithm
              example: es384
        verification_logs_count:
          type: integer
          minimum: 0
          description: Number of verification attempts for this credential
          example: 5
        updated_at:
          type: string
          format: date-time
          description: When the credential was last updated
          example: '2025-01-20T14:30:00Z'
    CredentialIssuance:
      type: object
      description: A credential issuance record from the issuer's perspective
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the credential issuance
          example: 43861766-680a-4417-8657-9c22cc3d50fc
        status:
          type: string
          enum:
          - pending
          - issued
          - suspended
          - revoked
          - active
          - expired
          - archived
          example: active
          description: |-
            Current status of the credential/issuance:
            - pending: Created but not yet issued
            - issued: Credential has been signed and delivered
            - active: Credential is valid and can be verified
            - suspended: Temporarily disabled
            - revoked: Permanently invalidated
            - expired: Credential has passed its expiration date
            - archived: Credential has been archived
        subject_identifier:
          type: string
          description: Email or DID identifying the credential subject
          example: employee@acme-corp.com
        subject_identifier_type:
          type: string
          enum:
          - email
          - did
          description: Type of identifier used for the subject
          example: email
        issued_at:
          type: string
          format: date-time
          description: When the credential was issued
          example: '2025-01-15T10:00:00Z'
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the credential expires
          example: '2027-01-15T10:00:00Z'
        schema:
          type: object
          nullable: true
          properties:
            uuid:
              type: string
              format: uuid
              example: 03e5242c-5b6c-4e3f-9df8-5f4ddecb28c4
            name:
              type: string
              example: Employee Badge
            type:
              type: string
              example: EmployeeBadgeCredential
        issuer:
          type: object
          properties:
            name:
              type: string
              example: Acme Corporation
            did:
              type: string
              example: did:web:acme-corp.com
        verification_url:
          type: string
          format: uri
          description: URL to verify this credential
          example: https://aho.com/verify/391fde06-ced0-4a2e-b904-0d7e6bd2777c
        credential_jwt:
          type: string
          nullable: true
          description: The signed JWT credential token
          example: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
        created_at:
          type: string
          format: date-time
          example: '2025-01-15T09:55:00Z'
        subject_id:
          type: string
          nullable: true
          description: Internal subject identifier (detail view only)
          example: did:web:example.com:users:67890
        claims:
          type: object
          additionalProperties: true
          nullable: true
          description: Credential claims/attributes (detail view only)
          example:
            name: John Smith
            title: Senior Engineer
            department: Engineering
        vc_json:
          type: object
          additionalProperties: true
          nullable: true
          description: Raw VC JSON-LD document (detail view only)
        issuer_signing_key:
          allOf:
          - "$ref": "#/components/schemas/SigningKeyRef"
          description: Signing key used (detail view only)
        verification_logs_count:
          type: integer
          minimum: 0
          description: Number of verification attempts (detail view only)
          example: 3
        updated_at:
          type: string
          format: date-time
          description: When last updated (detail view only)
          example: '2025-01-20T14:30:00Z'
    Presentation:
      type: object
      description: A verifiable presentation with selective disclosure of claims
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the presentation
          example: 0dc32c8f-d774-4887-8338-6ca2d630608f
        credential_uuid:
          type: string
          format: uuid
          description: UUID of the source credential
          example: 8e732b14-c35f-4a7d-8c02-d9858581e125
        disclosed_claims:
          type: array
          items:
            type: string
          description: List of claim names included in this presentation
          example:
          - name
          - degree
        disclosed_values:
          type: object
          additionalProperties: true
          nullable: true
          description: The actual values of disclosed claims (dynamic, schema-dependent)
          example:
            name: Jane Doe
            degree: Bachelor of Science
        audience:
          type: string
          nullable: true
          description: Intended recipient of this presentation
          example: Acme Corp HR Department
        purpose:
          type: string
          nullable: true
          description: Why this presentation was created
          example: Employment verification
        status:
          type: string
          enum:
          - active
          - expired
          - revoked
          example: active
          description: |-
            Current status of the presentation:
            - active: Valid and can be verified
            - expired: Past its expiration date
            - revoked: Manually invalidated by the holder
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the presentation expires (null if no expiration)
          example: '2025-04-01T23:59:59Z'
        verification_count:
          type: integer
          minimum: 0
          description: Number of times this presentation has been verified
          example: 3
        created_at:
          type: string
          format: date-time
          description: When the presentation was created
          example: '2025-03-01T10:00:00Z'
        presentation_token:
          type: string
          description: The signed SD-JWT presentation token
          example: eyJhbGciOiJFUzI1NiJ9.eyJfc2QiOlsiLi4uIl19.signature~disclosure1~disclosure2
        share_data:
          type: object
          nullable: true
          description: Data for sharing this presentation
          properties:
            presentation_url:
              type: string
              format: uri
              description: Direct link to view/verify the presentation
              example: https://aho.com/verify/presentation/2baca3a0-62b5-4675-9507-d615e6fb1f05
            uuid:
              type: string
              format: uuid
              description: Presentation UUID for reference
              example: bca45724-2a5c-4a5e-acb2-19af7a96ca05
            credential_type:
              type: string
              description: Type of the source credential
              example: UniversityDegreeCredential
            issuer:
              type: string
              description: Name of the credential issuer
              example: Stanford University
            disclosed_claims:
              type: array
              items:
                type: string
              description: List of claim names included
              example:
              - name
              - degree
            expires_at:
              type: string
              format: date-time
              nullable: true
              description: When the presentation expires
              example: '2025-04-01T23:59:59Z'
      required:
      - uuid
      - credential_uuid
      - disclosed_claims
      - status
      - verification_count
      - created_at
    DataIntegrityCryptosuite:
      type: string
      enum:
      - ecdsa-rdfc-2019
      - ecdsa-jcs-2019
      - eddsa-rdfc-2022
      - eddsa-jcs-2022
      - ecdsa-sd-2023
      description: |-
        W3C Data Integrity cryptographic suite for signing credentials.

        **ECDSA suites** (require P-256 or P-384 signing key):
        - `ecdsa-rdfc-2019`: RDF Dataset Canonicalization
        - `ecdsa-jcs-2019`: JSON Canonicalization Scheme
        - `ecdsa-sd-2023`: Selective disclosure (holder can hide claims)

        **EdDSA suites** (require Ed25519 signing key):
        - `eddsa-rdfc-2022`: RDF Dataset Canonicalization
        - `eddsa-jcs-2022`: JSON Canonicalization Scheme

        Only `ecdsa-sd-2023` supports selective disclosure.
      example: ecdsa-sd-2023
    DataIntegrityConfig:
      type: object
      description: |-
        W3C Data Integrity format configuration for selective disclosure credentials.

        When using ecdsa-sd-2023 cryptosuite, the issuer can specify which claims are
        mandatory (always disclosed) vs selectable (holder can hide). Mandatory claims
        are embedded in the base proof at issuance time.

        **Cryptosuite compatibility:**
        - ECDSA suites (ecdsa-rdfc-2019, ecdsa-jcs-2019, ecdsa-sd-2023): Require P-256 or P-384 signing key
        - EdDSA suites (eddsa-rdfc-2022, eddsa-jcs-2022): Require Ed25519 signing key
        - Only ecdsa-sd-2023 supports selective disclosure
      properties:
        default_cryptosuite:
          allOf:
          - "$ref": "#/components/schemas/DataIntegrityCryptosuite"
          description: Default cryptographic suite for this schema's Data Integrity
            proofs.
        mandatory_pointers:
          type: array
          items:
            type: string
          description: |-
            RFC 6901 JSON Pointers for claims that MUST always be disclosed when using ecdsa-sd-2023.
            These are embedded in the base proof at issuance and cannot be hidden by the holder.
            Standard VC fields like /@context, /type, /issuer should typically be mandatory.
          example:
          - "/@context"
          - "/type"
          - "/issuer"
          - "/issuanceDate"
          - "/credentialSubject/type"
        selectable_claims:
          type: array
          items:
            type: string
          description: Claim names that holders can choose to hide (derived from subject_schema
            minus mandatory_pointers). Read-only.
          example:
          - email
          - dateOfBirth
          - address
          readOnly: true
      example:
        default_cryptosuite: ecdsa-sd-2023
        mandatory_pointers:
        - "/@context"
        - "/type"
        - "/issuer"
        - "/issuanceDate"
        - "/credentialSubject/type"
        - "/credentialSubject/id"
        selectable_claims:
        - email
        - phone
        - address
    IssuerCredentialSchema:
      type: object
      description: An issuer's credential schema with full details
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier
          example: 3314e46b-0645-4a25-9474-eed0b64277e8
        slug:
          type: string
          description: URL-friendly identifier
          example: employee-badge
        name:
          type: string
          description: Display name
          example: Employee Badge
        credential_type:
          type: string
          description: VC type identifier
          example: EmployeeBadgeCredential
        schema_type:
          type: string
          enum:
          - custom
          - education_credential
          - employment_credential
          - certificate
          - open_badge
          - clr
          description: Schema category
          example: employment_credential
        status:
          type: string
          enum:
          - draft
          - active
          - archived
          description: Schema status
          example: active
        supported_formats:
          type: array
          items:
            type: string
            enum:
            - jwt_vc
            - sd_jwt_vc
            - mdoc
            - data_integrity
          example:
          - jwt_vc
          - sd_jwt_vc
        template_key:
          type: string
          nullable: true
          example: employee_badge_v1
        credential_count:
          type: integer
          description: Number of credentials issued
          example: 150
        json_ld_context:
          type: array
          items:
            type: string
          description: JSON-LD context URLs
          example:
          - https://www.w3.org/2018/credentials/v1
        subject_schema:
          type: object
          additionalProperties: true
          description: JSON Schema for claims
        sd_jwt_vc_config:
          type: object
          additionalProperties: true
        mdoc_config:
          type: object
          additionalProperties: true
        data_integrity_config:
          "$ref": "#/components/schemas/DataIntegrityConfig"
        render_templates:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                description: Template identifier
                example: NpG7KMT8fbgav7VVzypF
              name:
                type: string
                example: Badge Card
              template_type:
                type: string
                enum:
                - custom
                - system
                example: custom
              output_format:
                type: string
                example: svg
        created_at:
          type: string
          format: date-time
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2025-01-15T10:30:00Z'
      required:
      - uuid
      - slug
      - name
      - credential_type
      - schema_type
      - status
      - supported_formats
      - credential_count
      - created_at
      - updated_at
    CredentialSchema:
      type: object
      description: A template defining the structure of a credential
      properties:
        slug:
          type: string
          pattern: "^[a-z0-9]+(-[a-z0-9]+)*$"
          example: university-degree
          description: URL-friendly identifier (lowercase, hyphenated)
        name:
          type: string
          minLength: 1
          example: University Degree
          description: Human-readable name of the schema
        description:
          type: string
          description: Detailed description of what this credential type represents
          example: A credential representing an academic degree from a university
        credential_type:
          type: string
          pattern: "^[a-zA-Z][a-zA-Z0-9]*$"
          example: UniversityDegreeCredential
          description: Credential type identifier (e.g., PascalCase or standard like
            mDL)
        category:
          type: string
          description: Category for organizing schemas
          example: education
        visibility:
          type: string
          enum:
          - public
          - private
          example: public
          description: |-
            Schema visibility:
            - public: Listed in the public schema catalog for anyone to use
            - private: Only visible to the owning issuer organization
        claims:
          type: array
          description: List of claim fields defined in this schema
          items:
            type: object
            properties:
              name:
                type: string
                minLength: 1
                description: Claim field name
                example: degree
              type:
                type: string
                enum:
                - string
                - integer
                - boolean
                - date
                - datetime
                example: string
                description: |-
                  Data type of the claim:
                  - string: Text value
                  - integer: Whole number
                  - boolean: True/false value
                  - date: Date only (YYYY-MM-DD)
                  - datetime: Date and time (ISO 8601)
              required:
                type: boolean
                description: Whether this claim is required when issuing
                example: true
        tags:
          type: array
          items:
            type: string
            minLength: 1
          description: Tags for filtering and discovery
          example:
          - degree
          - academic
          - diploma
        url:
          type: string
          format: uri
          description: URL to the schema documentation page
        context_url:
          type: string
          format: uri
          description: URL to the JSON-LD context document
          example: https://aho.com/contexts/university-degree
        external_url:
          type: string
          format: uri
          nullable: true
          description: URL to external schema definition (e.g., schema.org)
          example: https://schema.org/EducationalOccupationalCredential
        source:
          type: string
          nullable: true
          description: Source of the schema (e.g., 'schema_org', 'custom')
          example: custom
        subject_schema:
          type: object
          additionalProperties: true
          nullable: true
          description: JSON Schema defining the credential subject structure
        json_ld_context:
          type: array
          items:
            type: string
          nullable: true
          description: JSON-LD context URLs for this schema
          example:
          - https://www.w3.org/2018/credentials/v1
        svg_template_key:
          type: string
          nullable: true
          description: Key identifying the SVG template used for rendering
          example: university_diploma
    RenderTemplate:
      type: object
      description: A visual rendering template for credentials (SVG or PDF)
      properties:
        id:
          type: string
          description: Unique template identifier
          example: nZaPYEp78T82P57z0NRl
        name:
          type: string
          minLength: 1
          description: Human-readable template name
          example: Employee Badge
        description:
          type: string
          nullable: true
          description: Description of the template
          example: Professional badge design for employee credentials
        render_suite:
          type: string
          enum:
          - svg_mustache
          - pdf_mustache
          example: svg_mustache
          description: |-
            Template rendering engine:
            - svg_mustache: SVG template with Mustache variables
            - pdf_mustache: HTML template converted to PDF
        template_type:
          type: string
          enum:
          - custom
          - system
          example: custom
          description: |-
            Template origin:
            - custom: Created by issuer via API or dashboard
            - system: Built-in template (cannot be modified or deleted)
        media_type:
          type: string
          enum:
          - image/svg+xml
          - application/pdf
          example: image/svg+xml
          description: MIME type of the rendered output
        digest_multibase:
          type: string
          description: SHA-256 hash of template content (multibase base64url encoded)
          example: uQvLKPJfT5c...
        render_properties:
          type: array
          items:
            type: string
          nullable: true
          description: JSON Pointers to claims rendered by this template
          example:
          - "/credentialSubject/name"
          - "/credentialSubject/employer"
        exposed_fields:
          type: array
          items:
            type: string
          description: Field names extracted from render_properties
          example:
          - name
          - employer
        content:
          type: string
          nullable: true
          description: Template content (only included when specifically requested)
          example: "<svg>...</svg>"
        created_at:
          type: string
          format: date-time
          description: When the template was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the template was last updated
          example: '2025-01-15T10:30:00Z'
      required:
      - id
      - name
      - render_suite
      - template_type
      - media_type
      - digest_multibase
      - created_at
      - updated_at
    RenderTemplateValidationResult:
      type: object
      description: Result of template validation without saving
      properties:
        success:
          type: boolean
          description: Whether the API call succeeded
          example: true
        valid:
          type: boolean
          description: Whether the template is valid
          example: true
        digest_multibase:
          type: string
          nullable: true
          description: Computed hash (only if valid)
          example: uQvLKPJfT5cXyz123...
        extracted_variables:
          type: array
          items:
            type: string
          description: Mustache variables found in the template
          example:
          - name
          - employer
          - jobTitle
        errors:
          type: array
          items:
            type: string
          description: Validation errors (only if invalid)
          example: []
        warnings:
          type: array
          items:
            type: string
          description: Non-fatal warnings about the template
          example: []
    CredentialOfferResult:
      type: object
      description: Result of creating a credential offer
      properties:
        offer_id:
          type: string
          format: uuid
          description: Unique identifier for the offer (used in URLs)
          example: 5e318536-d82a-46b2-b829-f11eda8c4da5
        offer_uri:
          type: string
          format: uri
          description: URL where the offer can be retrieved (for credential_offer_uri)
          example: https://issuer.example.com/credential_offers/550e8400-e29b-41d4-a716-446655440000
        deep_link:
          type: string
          format: uri
          description: Deep link for wallet apps (openid-credential-offer://)
          example: openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.example.com%2Fcredential_offers%2F550e8400
        tx_code:
          type: string
          nullable: true
          description: PIN/tx_code the holder must enter to claim (only if require_tx_code
            was true, OID4VCI 1.0)
          example: '123456'
        expires_at:
          type: string
          format: date-time
          description: When the offer expires
          example: '2025-01-16T12:00:00Z'
      required:
      - offer_id
      - offer_uri
      - deep_link
      - expires_at
    WebhookPayload:
      type: object
      description: |-
        Payload sent to verifier webhook endpoints when a holder responds to a presentation request.
        The webhook includes an X-Webhook-Signature header for verification (HMAC-SHA256 of timestamp.payload using API key).
        Verifiers should validate this signature before processing the payload.
      properties:
        event:
          type: string
          enum:
          - presentation_response.approved
          - presentation_response.declined
          example: presentation_response.approved
          description: |-
            Event type indicating the holder's response:
            - presentation_response.approved: Holder approved and shared their credentials
            - presentation_response.declined: Holder declined the presentation request
        timestamp:
          type: string
          format: date-time
          description: When this webhook event was generated (ISO 8601)
          example: '2025-01-15T14:30:00Z'
        request:
          type: object
          description: The original presentation request that was responded to
          properties:
            uuid:
              type: string
              format: uuid
              description: Unique identifier of the presentation request
              example: 1bb5aa07-ce50-45ee-a950-74daac1e9c18
            name:
              type: string
              description: Name/title of the presentation request
              example: Employment Verification
            purpose:
              type: string
              description: Why the verifier requested this information
              example: Verify employment history for job application
            required_claims:
              type: array
              items:
                type: string
              description: Claims that were required to be disclosed
              example:
              - name
              - employer
              - job_title
            optional_claims:
              type: array
              items:
                type: string
              description: Claims that were optionally requested
              example:
              - start_date
              - end_date
        response:
          type: object
          description: The holder's response to the request
          properties:
            uuid:
              type: string
              format: uuid
              description: Unique identifier of the response
              example: 25234973-b39f-4a0a-aa66-4271587b0407
            status:
              type: string
              enum:
              - approved
              - declined
              description: |-
                The holder's decision:
                - approved: Holder agreed to share the requested claims
                - declined: Holder refused the request
            responded_at:
              type: string
              format: date-time
              description: When the holder responded
              example: '2025-01-15T14:25:00Z'
        verifier:
          type: object
          description: The organization that made the presentation request
          properties:
            id:
              type: string
              description: Verifier account identifier
              example: nZaPYEp78T82P57z0NRl
            name:
              type: string
              description: Organization name
              example: Acme Corp HR
        holder:
          type: object
          nullable: true
          description: Information about the credential holder (only present for approved
            responses)
          properties:
            name:
              type: string
              description: Holder's display name
              example: John Doe
        disclosed_claims:
          type: object
          additionalProperties: true
          nullable: true
          description: The actual claim values disclosed by the holder (only present
            for approved responses)
          example:
            name: John Doe
            employer: Tech Corp
            job_title: Software Engineer
        credential:
          type: object
          nullable: true
          description: Information about the source credential (only present for approved
            responses)
          properties:
            uuid:
              type: string
              format: uuid
              description: Credential unique identifier
              example: dc42ad70-f662-4e82-8958-6f40a4022cb8
            type:
              type: string
              description: Credential type
              example: EmploymentCredential
            schema:
              type: string
              description: Schema name the credential is based on
              example: Employment Record
            issuer:
              type: object
              description: Organization that issued the credential
              properties:
                name:
                  type: string
                  description: Issuer organization name
                  example: Tech Corp
                did:
                  type: string
                  description: Issuer's Decentralized Identifier
                  example: did:web:techcorp.example
            status:
              type: string
              enum:
              - active
              - suspended
              - revoked
              example: active
              description: |-
                Current status of the credential:
                - active: Credential is valid and verifiable
                - suspended: Temporarily disabled by issuer
                - revoked: Permanently invalidated by issuer
            issued_at:
              type: string
              format: date-time
              description: When the credential was issued
              example: '2024-06-01T00:00:00Z'
            expires_at:
              type: string
              format: date-time
              nullable: true
              description: When the credential expires (null if no expiration)
              example: '2025-06-01T00:00:00Z'
      required:
      - event
      - timestamp
      - request
      - response
      - verifier
    BatchOperationResult:
      type: object
      description: |-
        Result of a batch operation (revoke_batch, suspend_batch, reinstate_batch).
        Contains per-UUID results for debugging and summary counts.
      properties:
        items:
          type: array
          description: Per-UUID results in submission order
          items:
            type: object
            properties:
              uuid:
                type: string
                format: uuid
                description: The credential UUID
                example: 20ee86cc-9a3f-45df-9c64-21a3dfd5d38c
              status:
                type: string
                description: Result status for this credential
                enum:
                - already_active
                - already_revoked
                - already_suspended
                - cannot_reinstate
                - cannot_suspend
                - not_found
                - reinstated
                - revoked
                - suspended
                example: revoked
            required:
            - uuid
            - status
        summary:
          type: object
          description: Aggregate counts by result status
          properties:
            total:
              type: integer
              description: Total UUIDs processed
              example: 10
            revoked:
              type: integer
              description: Credentials successfully revoked (revoke_batch)
              example: 8
            suspended:
              type: integer
              description: Credentials successfully suspended (suspend_batch)
              example: 0
            reinstated:
              type: integer
              description: Credentials successfully reinstated (reinstate_batch)
              example: 0
            not_found:
              type: integer
              description: UUIDs that didn't match any credential
              example: 1
            already_revoked:
              type: integer
              description: Credentials already revoked
              example: 1
            already_suspended:
              type: integer
              description: Credentials already suspended
              example: 0
            already_active:
              type: integer
              description: Credentials already in active state
              example: 0
            cannot_suspend:
              type: integer
              description: Credentials that cannot be suspended (e.g., revoked)
              example: 0
            cannot_reinstate:
              type: integer
              description: Credentials that cannot be reinstated (e.g., revoked)
              example: 0
          required:
          - total
      required:
      - items
      - summary
    CredentialOffer:
      type: object
      description: A credential offer that holders can claim via wallet apps (OID4VCI)
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the offer
          example: e8738e4f-2867-485d-9a00-fbe913ffca20
        status:
          type: string
          enum:
          - pending
          - accepted
          - expired
          - revoked
          example: pending
          description: |-
            Current status of the offer:
            - pending: Awaiting holder claim
            - accepted: Successfully claimed by holder
            - expired: Past expiration time
            - revoked: Cancelled by issuer before claim
        subject_identifier:
          type: string
          nullable: true
          description: Email or DID of the intended recipient
          example: student@university.edu
        subject_claims:
          type: object
          additionalProperties: true
          description: Pre-filled claim values for the credential
          example:
            name: Jane Doe
            degree: Bachelor of Science
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the offer expires
          example: '2025-02-15T23:59:59Z'
        created_at:
          type: string
          format: date-time
          description: When the offer was created
          example: '2025-01-15T10:00:00Z'
        schema:
          type: object
          description: The credential schema for this offer
          properties:
            uuid:
              type: string
              format: uuid
              example: 7dceea59-9eef-406c-bca9-acaa0211bf8a
            name:
              type: string
              description: Schema display name
              example: University Degree
            slug:
              type: string
              description: URL-friendly schema identifier
              example: university-degree
        offer_uri:
          type: string
          format: uri
          nullable: true
          description: URL where the offer can be retrieved (included on show)
          example: https://aho.com/openid4vci/offers/027b08a5-83e6-4cb3-b20e-8c5c9d517363
        deep_link:
          type: string
          nullable: true
          description: Deep link for wallet apps (openid-credential-offer://...) (included
            on show)
          example: openid-credential-offer://?credential_offer_uri=https%3A%2F%2Faho.com%2Fopenid4vci%2Foffers%2Fcb20c0ad
      required:
      - uuid
      - status
      - subject_claims
      - created_at
      - schema
    PresentationRequest:
      type: object
      description: An OpenID4VP presentation request created by a verifier
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the presentation request
          example: 4f0769f1-d7be-429e-a316-d28ff0cae1b6
        name:
          type: string
          description: Display name for the request
          example: Age Verification
        purpose:
          type: string
          nullable: true
          description: Purpose shown to holder explaining why claims are needed
          example: Verify you are over 21 to purchase alcohol
        status:
          type: string
          enum:
          - draft
          - active
          - expired
          - closed
          example: active
          description: |-
            Current status of the request:
            - draft: Not yet activated
            - active: Accepting responses
            - expired: Past expiration time
            - closed: Manually closed by verifier
        query_format:
          type: string
          enum:
          - presentation_exchange
          - dcql
          example: presentation_exchange
          description: |-
            Query format used:
            - dcql: Digital Credentials Query Language (OpenID4VP native)
            - presentation_exchange: DIF Presentation Exchange format
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the request expires
          example: '2025-01-16T23:59:59Z'
        max_responses:
          type: integer
          nullable: true
          description: Maximum number of responses allowed (null = unlimited)
          example: 1
        callback_url:
          type: string
          format: uri
          nullable: true
          description: Webhook URL for response notifications
          example: https://example.com/webhooks/presentation
        redirect_url:
          type: string
          format: uri
          nullable: true
          description: Where to redirect holder after response
          example: https://example.com/verification-complete
        created_at:
          type: string
          format: date-time
          description: When the request was created
          example: '2025-01-15T10:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the request was last updated
          example: '2025-01-15T10:00:00Z'
        verifier:
          type: object
          description: The verifier organization
          properties:
            name:
              type: string
              description: Organization name
              example: Acme Bar & Grill
            domain:
              type: string
              nullable: true
              description: Verified domain
              example: acme-bar.com
        urls:
          type: object
          nullable: true
          description: URLs for accessing/sharing the request (included on show)
          properties:
            dashboard_url:
              type: string
              format: uri
              description: Human-viewable dashboard URL
              example: https://aho.com/verify/a1cc92eb-839d-4ab8-a843-d6c0fea6d68a
            openid4vp_uri:
              type: string
              description: Wallet deep link (openid4vp://...)
              example: openid4vp://authorize?request_uri=https%3A%2F%2F...
            request_uri:
              type: string
              format: uri
              description: Raw JAR endpoint URL
              example: https://aho.com/openid4vp/requests/beef8d2e-61bd-4564-8a3b-5a211aafc1d0
            qr_code_data:
              type: string
              description: Data for QR code generation
              example: openid4vp://authorize?request_uri=...
        stats:
          type: object
          nullable: true
          description: Response statistics (included on show)
          properties:
            response_count:
              type: integer
              description: Total responses received
              example: 5
            approved_count:
              type: integer
              description: Approved responses
              example: 4
            pending_count:
              type: integer
              description: Pending responses
              example: 1
        dcql_query:
          type: object
          additionalProperties: true
          nullable: true
          description: DCQL query definition (only for dcql format)
          example:
            credentials:
            - id: age_cred
              format: vc+sd-jwt
              claims:
              - path:
                - birthDate
          properties:
            credentials:
              type: array
              items:
                type: object
                additionalProperties: true
            credential_sets:
              type: array
              items:
                type: object
                additionalProperties: true
              nullable: true
        presentation_definition:
          type: object
          additionalProperties: true
          nullable: true
          description: Presentation Exchange definition (only for presentation_exchange
            format)
          example:
            id: request_1
            input_descriptors:
            - id: age_verification
              constraints:
                fields:
                - path:
                  - "$.birthDate"
          properties:
            input_descriptors:
              type: array
              items:
                type: object
                additionalProperties: true
      required:
      - uuid
      - name
      - status
      - query_format
      - created_at
      - updated_at
      - verifier
    PresentationResponse:
      type: object
      description: A holder's response to a presentation request
      properties:
        uuid:
          type: string
          format: uuid
          description: Unique identifier for the response
          example: '08eb90df-d436-4214-82a9-cf67ce2158c4'
        status:
          type: string
          enum:
          - pending
          - approved
          - declined
          example: approved
          description: |-
            Status of the response:
            - pending: Awaiting holder action
            - approved: Holder shared requested credentials
            - declined: Holder declined the request
        responded_at:
          type: string
          format: date-time
          nullable: true
          description: When the holder responded
          example: '2025-01-15T14:30:00Z'
        created_at:
          type: string
          format: date-time
          description: When the response record was created
          example: '2025-01-15T14:25:00Z'
        holder:
          type: object
          nullable: true
          description: Information about the holder (if available)
          properties:
            name:
              type: string
              description: Holder's display name
              example: John Doe
        disclosed_claims:
          type: object
          additionalProperties: true
          nullable: true
          description: Claims disclosed by the holder (detail view only)
          example:
            name: John Doe
            age_over_21: true
        claim_mapping:
          type: object
          additionalProperties: true
          nullable: true
          description: Mapping of claim names (detail view only)
        credential:
          type: object
          nullable: true
          description: Source credential information (detail view only, if single
            credential)
          properties:
            uuid:
              type: string
              format: uuid
              example: fa41d8af-469e-4aa8-8d96-e5e7401ea22d
            type:
              type: string
              description: Credential type
              example: AgeVerificationCredential
            issuer:
              type: object
              properties:
                name:
                  type: string
                  example: State DMV
                did:
                  type: string
                  example: did:web:dmv.state.gov
            issued_at:
              type: string
              format: date-time
              example: '2025-01-01T00:00:00Z'
            expires_at:
              type: string
              format: date-time
              nullable: true
              example: '2030-01-01T00:00:00Z'
        credentials:
          type: array
          nullable: true
          description: Multiple credentials (detail view only, for multi-credential
            responses)
          items:
            type: object
            properties:
              query_item_id:
                type: string
                description: ID from the DCQL query
                example: age_cred
              credential:
                type: object
                properties:
                  uuid:
                    type: string
                    format: uuid
                    example: 93d1dc9b-84eb-4a0e-bede-9c0c66a75d8f
                  type:
                    type: string
                    example: AgeVerificationCredential
              disclosed_claims:
                type: object
                additionalProperties: true
                example:
                  over_21: true
      required:
      - uuid
      - status
      - created_at
    DataSource:
      type: object
      description: A data source for automated credential issuance
      properties:
        slug:
          type: string
          description: URL-friendly identifier
          example: employee-database
        name:
          type: string
          description: Display name for the data source
          example: Employee Database
        source_type:
          type: string
          enum:
          - postgresql
          - csv
          example: postgresql
          description: |-
            Type of data source:
            - postgresql: PostgreSQL database connection
            - csv: CSV file upload
        status:
          type: string
          enum:
          - draft
          - active
          - paused
          - error
          example: active
          description: |-
            Current status of the data source:
            - draft: Not yet configured/tested
            - active: Connection verified, ready for use
            - paused: Temporarily disabled
            - error: Connection test failed
        mapping_count:
          type: integer
          minimum: 0
          description: Number of credential schema mappings using this source
          example: 3
        connection_info:
          type: object
          nullable: true
          description: Connection metadata (passwords are never exposed)
          properties:
            host:
              type: string
              description: Database hostname
              example: db.example.com
            port:
              type: integer
              description: Database port
              example: 5432
            database:
              type: string
              description: Database name
              example: hr_system
            username:
              type: string
              description: Connection username
              example: reader
        source_file:
          type: object
          nullable: true
          description: CSV file details (for csv source type)
          properties:
            filename:
              type: string
              example: employees.csv
            byte_size:
              type: integer
              example: 15240
            content_type:
              type: string
              example: text/csv
        created_at:
          type: string
          format: date-time
          description: When the data source was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the data source was last updated
          example: '2025-01-15T10:30:00Z'
      required:
      - slug
      - name
      - source_type
      - status
      - mapping_count
      - created_at
      - updated_at
    DataSourceMapping:
      type: object
      description: A mapping between a data source and credential schema
      properties:
        slug:
          type: string
          description: URL-friendly identifier
          example: employee-database-employee-badge
        name:
          type: string
          nullable: true
          description: Optional custom name for the mapping
          example: Employee Badge Mapping
        display_name:
          type: string
          description: Display name (custom name or auto-generated)
          example: Employee Database → Employee Badge
        data_source:
          type: object
          description: The linked data source
          properties:
            slug:
              type: string
              example: employee-database
            name:
              type: string
              example: Employee Database
            source_type:
              type: string
              enum:
              - postgresql
              - csv
              example: postgresql
        credential_schema:
          type: object
          description: The linked credential schema
          properties:
            uuid:
              type: string
              format: uuid
              example: 60476b28-5bfc-4cd5-a65a-9ac898a7223c
            slug:
              type: string
              example: employee-badge
            name:
              type: string
              example: Employee Badge
        field_mapping:
          type: object
          additionalProperties: true
          nullable: true
          description: Maps data source columns to credential claims (full view only)
          example:
            name: full_name
            email: email_address
        query_config:
          type: object
          additionalProperties: true
          nullable: true
          description: Query configuration for data extraction (full view only)
          example:
            table: employees
            columns:
            - full_name
            - email_address
        automation_count:
          type: integer
          minimum: 0
          description: Number of automations using this mapping
        created_at:
          type: string
          format: date-time
          description: When the mapping was created
        updated_at:
          type: string
          format: date-time
          description: When the mapping was last updated
      required:
      - slug
      - display_name
      - data_source
      - credential_schema
      - automation_count
      - created_at
      - updated_at
    DataSourceTestResult:
      type: object
      description: Result of testing a data source connection
      properties:
        message:
          type: string
          description: Human-readable result message
          example: Connection successful
        status:
          type: string
          enum:
          - connected
          - error
          example: connected
          description: |-
            Connection test result:
            - connected: Connection test passed
            - error: Connection test failed
        error:
          type: string
          nullable: true
          description: Error message if connection failed
          example:
      required:
      - message
      - status
    CredentialAutomation:
      type: object
      description: An automated credential issuance policy
      properties:
        id:
          type: string
          description: Unique identifier (hashid)
          example: abc123xyz
        name:
          type: string
          description: Display name for the automation
          example: Daily Badge Sync
        trigger_mode:
          type: string
          enum:
          - manual
          - scheduled
          - webhook
          example: scheduled
          description: |-
            How the automation is triggered:
            - manual: Triggered via API or dashboard
            - scheduled: Runs on cron schedule
            - webhook: Triggered via authenticated webhook
        status:
          type: string
          enum:
          - draft
          - active
          - paused
          - error
          example: active
          description: |-
            Current status:
            - draft: Not yet activated
            - active: Ready to run
            - paused: Temporarily disabled
            - error: Error state
        schedule:
          type: string
          nullable: true
          description: Cron expression for scheduled mode
          example: 0 0 * * *
        data_source_mapping:
          type: object
          description: The linked data source mapping
          properties:
            id:
              type: string
              example: badge-credential-mapping
            name:
              type: string
              example: Employee Database → Employee Badge
          required:
          - id
          - name
        account_domain:
          type: object
          description: The domain under which credentials are issued
          properties:
            id:
              type: string
              example: aEdOjwxyMwQBkxwgZjNG
            domain:
              type: string
              example: acme-corp.com
          required:
          - id
          - domain
        can_run:
          type: boolean
          description: Whether the automation can be triggered
          example: true
        running:
          type: boolean
          description: Whether the automation is currently running
          example: false
        last_run:
          type: object
          nullable: true
          description: Information about the last run (detail view only)
          properties:
            at:
              type: string
              format: date-time
              example: '2025-01-15T00:00:00Z'
            record_count:
              type: integer
              nullable: true
              example: 150
            error:
              type: string
              nullable: true
              example:
        webhook:
          type: object
          nullable: true
          description: Webhook configuration (webhook mode only, detail view)
          properties:
            configured:
              type: boolean
              description: Whether a webhook token is configured
              example: true
            enabled:
              type: boolean
              description: Whether webhook triggers are allowed
              example: true
        created_at:
          type: string
          format: date-time
          description: When the automation was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the automation was last updated
          example: '2025-01-15T10:30:00Z'
      required:
      - id
      - name
      - trigger_mode
      - status
      - data_source_mapping
      - account_domain
      - can_run
      - running
      - created_at
      - updated_at
    AutomationTriggerResult:
      type: object
      description: Result of triggering an automation
      properties:
        message:
          type: string
          description: Result message
          example: Automation triggered
        run_id:
          type: string
          description: Hashid of the created run log
          example: qFeHSnxBkguhubshOLT0
        status:
          type: string
          enum:
          - pending
          description: Initial status of the run
          example: pending
      required:
      - message
      - run_id
      - status
    AutomationWebhook:
      type: object
      description: Webhook configuration for an automation
      properties:
        automation_id:
          type: string
          description: The automation's unique identifier
          example: abc123xyz
        automation_name:
          type: string
          description: Display name of the automation
          example: Daily Badge Sync
        trigger_url:
          type: string
          format: uri
          description: Full URL to POST to trigger the automation
          example: https://api.aho.com/v1/hooks/automations/X_byFjHECwqaJccMOWumqjyJSNxZlEvV2JWL9XvF5VU
        token:
          type: string
          description: The webhook token (included in trigger_url)
          example: 32kbCpE2jTBD9ygyPOdcsIGIXpMLWvem0_0fOkydyks
        generated_at:
          type: string
          format: date-time
          nullable: true
          description: When the token was generated
          example: '2025-01-15T10:00:00Z'
        trigger_mode:
          type: string
          enum:
          - manual
          - scheduled
          - webhook
          description: Current trigger mode of the automation
          example: webhook
        enabled:
          type: boolean
          description: Whether webhook triggers are allowed (true when trigger_mode=webhook
            and status=active)
          example: true
      required:
      - automation_id
      - automation_name
      - trigger_url
      - token
      - trigger_mode
      - enabled
    AccountDomain:
      type: object
      description: A custom domain for the account's verifiable credentials
      properties:
        domain:
          type: string
          description: The domain name (also serves as unique identifier)
          example: trust.example.com
        did:
          type: string
          description: The DID derived from this domain
          example: did:web:trust.example.com
        primary:
          type: boolean
          description: Whether this is the primary domain for the account
          example: true
        fully_verified:
          type: boolean
          description: Whether both TXT and CNAME verification have passed
          example: true
        txt_status:
          type: string
          enum:
          - pending
          - verified
          - failed
          description: TXT record verification status
          example: verified
        txt_verified_at:
          type: string
          format: date-time
          nullable: true
          description: When TXT verification passed
          example: '2025-01-10T09:00:00Z'
        cname_verified:
          type: boolean
          description: Whether CNAME verification has passed
          example: true
        cname_verified_at:
          type: string
          format: date-time
          nullable: true
          description: When CNAME verification passed
          example: '2025-01-10T09:30:00Z'
        created_at:
          type: string
          format: date-time
          description: When the domain was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the domain was last updated
          example: '2025-01-10T09:30:00Z'
      required:
      - domain
      - did
      - primary
      - fully_verified
      - txt_status
      - cname_verified
      - created_at
      - updated_at
    AccountDomainVerification:
      type: object
      description: Domain verification instructions
      properties:
        txt:
          type: object
          properties:
            host:
              type: string
              description: DNS host for TXT record
              example: _aho_35ef2763-464d-4030-adb2-ae82a961e8ca.example.com
            value:
              type: string
              description: TXT record value
              example: 289a830e17ef62cf5e0ce5c6da37fe94a86a319d415fb39a37e3cb2282a1a61e
            instructions:
              type: string
              description: Human-readable instructions
              example: Add a TXT record with the specified value
        cname:
          type: object
          properties:
            host:
              type: string
              description: Domain to configure CNAME for
              example: trust.example.com
            target:
              type: string
              description: CNAME target
              example: customers.aho.com
            instructions:
              type: string
              description: Human-readable instructions
              example: Add a CNAME record pointing to the target
    DomainVerificationResult:
      type: object
      description: Result of domain verification check
      properties:
        domain:
          type: string
          description: The domain name
          example: trust.example.com
        fully_verified:
          type: boolean
          description: Whether both verifications passed
          example: true
        txt_verification:
          type: object
          properties:
            status:
              type: string
              example: verified
            verified:
              type: boolean
              example: true
            verified_at:
              type: string
              format: date-time
              nullable: true
              example: '2025-01-10T09:00:00Z'
            check_passed:
              type: boolean
              example: true
            error:
              type: string
              nullable: true
              example:
        cname_verification:
          type: object
          properties:
            verified:
              type: boolean
              example: true
            verified_at:
              type: string
              format: date-time
              nullable: true
              example: '2025-01-10T09:30:00Z'
            check_passed:
              type: boolean
              example: true
            error:
              type: string
              nullable: true
              example:
    SigningKey:
      type: object
      description: A cryptographic signing key for verifiable credentials
      properties:
        key_id:
          type: string
          description: Unique key identifier
          example: key-2962d38d-4ec8-454b-82b6-c553c37da055
        algorithm:
          type: string
          enum:
          - es256
          - es384
          - ed25519
          description: Cryptographic algorithm (ES256, ES384, or Ed25519)
          example: es256
        status:
          type: string
          enum:
          - pending
          - active
          - revoked
          - expired
          description: Key lifecycle status
          example: active
        usable:
          type: boolean
          description: Whether the key can be used for signing (active and not expired)
          example: true
        legacy:
          type: boolean
          description: Whether the key has been rotated and is in legacy grace period
          example: false
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the key expires (null = no expiration)
          example:
        created_at:
          type: string
          format: date-time
          description: When the key was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the key was last updated
          example: '2025-01-01T00:00:00Z'
      required:
      - key_id
      - algorithm
      - status
      - usable
      - legacy
      - created_at
      - updated_at
    SigningKeyDetails:
      allOf:
      - "$ref": "#/components/schemas/SigningKey"
      - type: object
        properties:
          public_key_jwk:
            type: object
            description: Public key in JWK format
            additionalProperties: true
          certificates:
            type: array
            description: Active certificates for this key
            items:
              type: object
              properties:
                domain:
                  type: string
                  example: trust.example.com
                type:
                  type: string
                  example: acme
                expires_at:
                  type: string
                  format: date-time
                  example: '2027-01-01T00:00:00Z'
                fingerprint:
                  type: string
                  example: SHA256:abc123...
          did_verification_method:
            type: string
            description: DID verification method ID
            example: did:web:trust.example.com#key-05b4fffb-9e21-4e80-9a06-5636cb740f2f
          did_key:
            type: string
            description: did:key identifier derived from public key
            example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
    KeyRotationResult:
      type: object
      description: Result of key rotation
      properties:
        message:
          type: string
          example: Key rotated successfully. Old key marked as legacy and will be
            auto-revoked after grace period.
        old_key:
          "$ref": "#/components/schemas/SigningKey"
        new_key:
          "$ref": "#/components/schemas/SigningKey"
    CertificateResponse:
      type: object
      description: X.509 certificate for a signing key
      properties:
        domain:
          type: string
          description: Domain the certificate is for
          example: trust.example.com
        key_id:
          type: string
          description: Signing key identifier
          example: key-e5ee0524-3cfc-437b-af2e-5723ea295bbf
        certificate_type:
          type: string
          enum:
          - self_signed
          - acme
          - uploaded
          description: How the certificate was obtained
          example: acme
        subject:
          type: string
          description: Certificate subject common name
          example: CN=trust.example.com
        issuer:
          type: string
          description: Certificate issuer common name
          example: CN=Let's Encrypt Authority X3
        expires_at:
          type: string
          format: date-time
          description: When the certificate expires
          example: '2027-01-01T00:00:00Z'
        san_dns_names:
          type: array
          items:
            type: string
          description: Subject alternative DNS names
          example:
          - trust.example.com
        certificate_chain_pem:
          type: array
          items:
            type: string
          description: PEM-encoded certificate chain
          example:
          - |-
            -----BEGIN CERTIFICATE-----
            ...
    ApiKey:
      type: object
      description: |-
        An API key for programmatic access.

        Each account has one secret key and one publishable key:
        - **Secret keys**: For server-to-server API calls. Masked in responses.
        - **Publishable keys**: For browser-based requests. Always shown in full.
      properties:
        id:
          type: string
          description: Unique key identifier (hashid)
          example: apikey_abc123
        type:
          type: string
          enum:
          - secret_key
          - publishable_key
          description: Key type
          example: secret_key
        name:
          type: string
          description: Display name for the key
          example: Secret Key
        status:
          type: string
          enum:
          - pending
          - active
          - revoked
          - expired
          description: Key lifecycle status
          example: active
        usable:
          type: boolean
          description: Whether the key can be used (active and not expired)
          example: true
        allowed_sources:
          type: array
          items:
            type: string
          description: Allowed IPs/CIDRs (secret keys) or origins (publishable keys)
          example:
          - 192.168.1.0/24
        key:
          type: string
          nullable: true
          description: Full key value. Always shown for publishable keys; only on
            regeneration for secret keys.
          example: aho_pub_abc123...
        masked_key:
          type: string
          nullable: true
          description: Masked key (secret keys only)
          example: aho_sec_abc...xyz
        last_used_at:
          type: string
          format: date-time
          nullable: true
          description: When the key was last used
          example: '2025-03-15T10:30:00Z'
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: When the key expires
          example:
        created_at:
          type: string
          format: date-time
          description: When the key was created
          example: '2025-01-01T00:00:00Z'
        updated_at:
          type: string
          format: date-time
          description: When the key was last updated
          example: '2025-03-15T10:30:00Z'
      required:
      - id
      - type
      - name
      - status
      - usable
      - allowed_sources
      - created_at
      - updated_at
    ApiKeyRegenerationResponse:
      type: object
      properties:
        message:
          type: string
          example: API key regenerated. The old key value no longer works.
        api_key:
          "$ref": "#/components/schemas/ApiKey"
        warning:
          type: string
          nullable: true
          description: Security warning (secret keys only)
          example: Store this key securely. It will not be shown again.
    ApiKeyUpdateResponse:
      type: object
      properties:
        message:
          type: string
          example: API key updated successfully
        api_key:
          "$ref": "#/components/schemas/ApiKey"
    Webhook:
      type: object
      description: A webhook endpoint for receiving event notifications
      properties:
        id:
          type: string
          description: Webhook identifier (currently always 'primary')
          example: primary
        url:
          type: string
          format: uri
          description: The webhook endpoint URL
          example: https://example.com/webhook
        configured:
          type: boolean
          description: Whether the webhook is configured
          example: true
        created_at:
          type: string
          format: date-time
          nullable: true
          description: When the webhook was created (not currently tracked)
          example: '2025-01-15T09:00:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          description: When the webhook was last updated (not currently tracked)
          example: '2025-02-20T14:30:00Z'
      required:
      - id
      - url
      - configured
    WebhookTestResult:
      type: object
      description: Result of testing a webhook endpoint
      properties:
        message:
          type: string
          description: Result message
          example: Webhook test successful
        status_code:
          type: integer
          nullable: true
          description: HTTP status code from the webhook endpoint
          example: 200
        error:
          type: string
          nullable: true
          description: Error message if the test failed
          example:
    UpdateApiKeyParams:
      type: object
      description: Parameters for updating an API key
      properties:
        api_key:
          type: object
          properties:
            allowed_sources:
              type: array
              items:
                type: string
              description: Allowed IPs/CIDRs (secret keys) or origins (publishable
                keys)
              example:
              - 192.168.1.0/24
              - 10.0.0.1
    CreateDomainParams:
      type: object
      description: Parameters for registering a domain
      properties:
        domain:
          type: string
          description: Domain name to register
          example: trust.example.com
      required:
      - domain
    CreateSigningKeyParams:
      type: object
      description: Parameters for generating a signing key
      properties:
        algorithm:
          type: string
          enum:
          - es256
          - es384
          - ed25519
          description: 'Cryptographic algorithm (default: es256)'
          example: es256
        activate:
          type: boolean
          description: 'Activate immediately (default: true)'
          example: true
    RotateSigningKeyParams:
      type: object
      description: Parameters for rotating a signing key
      properties:
        algorithm:
          type: string
          enum:
          - es256
          - es384
          - ed25519
          description: 'Algorithm for new key (default: same as old key)'
          example: es256
    CreateWebhookParams:
      type: object
      description: Parameters for configuring a webhook
      properties:
        url:
          type: string
          format: uri
          description: Webhook endpoint URL
          example: https://example.com/webhooks/credentials
      required:
      - url
    UpdateWebhookParams:
      type: object
      description: Parameters for updating a webhook
      properties:
        url:
          type: string
          format: uri
          description: New webhook endpoint URL
          example: https://example.com/webhooks/credentials-v2
    CreatePresentationParams:
      type: object
      description: Parameters for creating a selective disclosure presentation
      properties:
        credential_uuid:
          type: string
          format: uuid
          description: UUID of the credential to present
          example: f27a22e1-c304-4316-a0c8-1d5706b8794a
        disclosed_claims:
          type: array
          items:
            type: string
          description: Claim names to disclose
          example:
          - name
          - email
          - birthDate
        audience:
          type: string
          description: Intended recipient of the presentation
          example: https://verifier.example.com
        purpose:
          type: string
          description: Purpose of the presentation
          example: Age verification for online purchase
        expires_in:
          type: integer
          description: Expiration in seconds from now
          example: 3600
      required:
      - credential_uuid
      - disclosed_claims
    VerifyPresentationParams:
      type: object
      description: Parameters for verifying a presentation
      properties:
        token:
          type: string
          description: The SD-JWT presentation token to verify
          example: eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lzc3Vlci5leGFtcGxlLmNvbSJ9.signature~disclosure1~disclosure2~
      required:
      - token
    CreatePresentationRequestParams:
      type: object
      description: Parameters for creating a presentation request
      properties:
        name:
          type: string
          description: Display name for the request
          example: Age Verification
        purpose:
          type: string
          description: Purpose shown to holder explaining why claims are needed
          example: We need to verify you are over 21 to complete this purchase
        query_format:
          type: string
          enum:
          - presentation_exchange
          - dcql
          description: 'Query format to use (default: dcql)'
          example: presentation_exchange
        dcql_query:
          type: object
          description: DCQL query definition (for dcql format)
          example:
            credentials:
            - id: age_cred
              format: vc+sd-jwt
              claims:
              - path:
                - birthDate
        presentation_definition:
          type: object
          description: Presentation Exchange definition (for presentation_exchange
            format)
          example:
            id: age_verification_request
            input_descriptors:
            - id: age_credential
              name: Age Verification
              purpose: Verify you are over 21
              constraints:
                fields:
                - path:
                  - "$.credentialSubject.birthDate"
        expires_in:
          type: integer
          description: Expiration in seconds from now
          example: 86400
        max_responses:
          type: integer
          description: Maximum number of responses allowed
          example: 1
        callback_url:
          type: string
          format: uri
          description: Webhook URL for response notifications
          example: https://example.com/webhooks/presentations
        redirect_url:
          type: string
          format: uri
          description: Where to redirect holder after response
          example: https://example.com/verification-complete
      required:
      - name
    UpdatePresentationRequestParams:
      type: object
      description: Parameters for updating a presentation request
      properties:
        name:
          type: string
          description: Display name for the request
          example: Updated Age Verification
        purpose:
          type: string
          description: Purpose shown to holder
          example: We need to verify your age for compliance
        callback_url:
          type: string
          format: uri
          description: Webhook URL for response notifications
          example: https://example.com/webhooks/presentations-v2
        redirect_url:
          type: string
          format: uri
          description: Where to redirect holder after response
          example: https://example.com/thank-you
    CreateAutomationParams:
      type: object
      description: Parameters for creating a credential automation
      properties:
        name:
          type: string
          description: Display name for the automation
          example: Employee Badge Automation
        data_source_mapping:
          type: string
          description: Data source mapping slug or hashid
          example: employee-badge-mapping
        account_domain:
          type: string
          description: Domain name or hashid (e.g., 'trust.example.com')
          example: trust.example.com
        trigger_mode:
          type: string
          enum:
          - manual
          - scheduled
          - webhook
          description: How the automation is triggered
          example: manual
        schedule:
          type: string
          description: Cron expression for scheduled mode
          example: 0 9 * * 1
      required:
      - name
      - data_source_mapping
      - account_domain
      - trigger_mode
    UpdateAutomationParams:
      type: object
      description: Parameters for updating an automation
      properties:
        name:
          type: string
          description: Display name for the automation
          example: Updated Employee Badge Automation
        trigger_mode:
          type: string
          enum:
          - manual
          - scheduled
          - webhook
          description: How the automation is triggered
          example: scheduled
        schedule:
          type: string
          description: Cron expression for scheduled mode
          example: 0 0 * * *
        status:
          type: string
          enum:
          - draft
          - active
          - paused
          description: Automation status
          example: active
    CreateCredentialParams:
      type: object
      description: Parameters for issuing a credential
      properties:
        schema_id:
          type: string
          description: Schema UUID or slug
          example: employee-badge
        subject_identifier:
          type: string
          description: Email or DID identifying the credential subject
          example: employee@example.com
        subject_identifier_type:
          type: string
          enum:
          - email
          - did
          description: Type of subject identifier
          example: email
        claims:
          type: object
          additionalProperties: true
          description: Credential claims (schema-dependent)
          example:
            name: Jane Smith
            employee_id: EMP-12345
            department: Engineering
        expires_in:
          type: integer
          description: Expiration in seconds from now
          example: 31536000
        signing_key_id:
          type: string
          description: Specific signing key to use (key_id from /account/signing_keys)
          example: key-3e96c61b-3710-49d7-b256-5c06f881e120
        cryptosuite:
          allOf:
          - "$ref": "#/components/schemas/DataIntegrityCryptosuite"
          description: Override the schema's default cryptosuite for this issuance
            (Data Integrity format only).
      required:
      - schema_id
      - subject_identifier
      - claims
    RevokeCredentialParams:
      type: object
      description: Parameters for revoking a credential
      properties:
        reason:
          type: string
          description: Reason for revocation (required for audit)
          example: Employee terminated
      required:
      - reason
    RevokeBatchParams:
      type: object
      description: Parameters for batch revoking credentials
      properties:
        uuids:
          type: array
          items:
            type: string
            format: uuid
          description: UUIDs of credentials to revoke (max 100)
          example:
          - 2774544e-7fcb-4dce-9d66-66d66c2df243
          - 11c31b3b-18e7-4e22-ab7d-b4fc7b996a40
        reason:
          type: string
          description: Reason for revocation
          example: Department reorganization
      required:
      - uuids
      - reason
    SuspendBatchParams:
      type: object
      description: Parameters for batch suspending credentials
      properties:
        uuids:
          type: array
          items:
            type: string
            format: uuid
          description: UUIDs of credentials to suspend (max 100)
          example:
          - 46dc3189-c0c6-489c-bad6-de0ffaaac902
          - 3979740b-5237-4405-ab9d-a9badcdd3edf
      required:
      - uuids
    ReinstateBatchParams:
      type: object
      description: Parameters for batch reinstating credentials
      properties:
        uuids:
          type: array
          items:
            type: string
            format: uuid
          description: UUIDs of credentials to reinstate (max 100)
          example:
          - 34cb9e29-0a5f-451d-85c8-b24892ef265c
          - 50d55f79-7904-4a0f-8205-0d33c0d49481
      required:
      - uuids
    CreateDataSourceMappingParams:
      type: object
      description: Parameters for creating a data source mapping
      properties:
        data_source_id:
          type: string
          description: ID of the data source
          example: employee-database
        credential_schema_id:
          type: string
          description: UUID or slug of the credential schema
          example: employee-badge
        name:
          type: string
          description: Optional custom name for the mapping
          example: HR Database to Employee Badge
        field_mapping:
          type: object
          additionalProperties: true
          description: Maps data source columns to credential claims
          example:
            name: full_name
            employee_id: emp_id
            department: dept_name
        query_config:
          type: object
          additionalProperties: true
          description: Query configuration for data extraction
          example:
            table: employees
            where: status = 'active'
      required:
      - data_source_id
      - credential_schema_id
      - field_mapping
    UpdateDataSourceMappingParams:
      type: object
      description: Parameters for updating a data source mapping
      properties:
        name:
          type: string
          description: Custom name for the mapping
          example: Updated HR Mapping
        field_mapping:
          type: object
          additionalProperties: true
          description: Maps data source columns to credential claims
          example:
            name: display_name
            employee_id: employee_number
        query_config:
          type: object
          additionalProperties: true
          description: Query configuration for data extraction
          example:
            table: employees
            where: status IN ('active', 'on_leave')
    PostgresqlConnectionSettings:
      type: object
      description: PostgreSQL connection settings
      properties:
        host:
          type: string
          description: Database server hostname or IP address
          example: db.example.com
        port:
          type: integer
          description: Database server port (1-65535)
          example: 5432
        database:
          type: string
          description: Name of the database to connect to
          example: hr_production
        username:
          type: string
          description: Database user for authentication (optional for local/trusted
            connections)
          example: readonly_user
        password:
          type: string
          description: Database password (optional for passwordless/trusted connections)
        sslmode:
          type: string
          description: 'SSL connection mode: prefer (try SSL first), require (must
            use SSL), disable (no SSL)'
          example: prefer
          enum:
          - prefer
          - require
          - disable
      required:
      - host
      - database
    CreateDataSourceParams:
      type: object
      description: Parameters for creating a data source
      properties:
        name:
          type: string
          description: Display name for the data source
          example: HR Database
        source_type:
          type: string
          enum:
          - postgresql
          - csv
          description: Type of data source
          example: postgresql
        connection_settings:
          "$ref": "#/components/schemas/PostgresqlConnectionSettings"
      required:
      - name
      - source_type
    UpdateDataSourceParams:
      type: object
      description: Parameters for updating a data source
      properties:
        name:
          type: string
          description: Display name for the data source
          example: HR Database (Production)
        connection_settings:
          "$ref": "#/components/schemas/PostgresqlConnectionSettings"
    CreateOfferParams:
      type: object
      description: Parameters for creating a credential offer
      properties:
        schema_id:
          type: string
          description: Schema UUID or slug
          example: employee-badge
        subject_identifier:
          type: string
          description: Email or unique ID of the intended recipient
          example: new.employee@example.com
        subject_claims:
          type: object
          additionalProperties: true
          description: Pre-filled claim values
          example:
            name: New Employee
            employee_id: EMP-NEW-001
        expires_in:
          type: integer
          description: Expiration in seconds from now
          example: 604800
        require_tx_code:
          type: boolean
          description: Require PIN/tx_code to claim (OID4VCI 1.0)
          example: true
      required:
      - schema_id
      - subject_claims
    CreateSchemaParams:
      type: object
      description: Parameters for creating a credential schema
      properties:
        name:
          type: string
          description: Display name for the schema
          example: Employee Badge
        credential_type:
          type: string
          description: PascalCase credential type identifier
          example: EmployeeBadgeCredential
        schema_type:
          type: string
          enum:
          - custom
          - education_credential
          - employment_credential
          - certificate
          - open_badge
          - clr
          description: Schema category
          example: custom
        subject_schema:
          type: object
          description: JSON Schema for credential claims
          example:
            type: object
            properties:
              name:
                type: string
              employee_id:
                type: string
            required:
            - name
            - employee_id
        supported_formats:
          type: array
          items:
            type: string
            enum:
            - jwt_vc
            - sd_jwt_vc
            - mdoc
            - data_integrity
          description: Supported credential formats
          example:
          - jwt_vc
          - sd_jwt_vc
        data_integrity_config:
          "$ref": "#/components/schemas/DataIntegrityConfig"
      required:
      - name
      - credential_type
      - schema_type
      - subject_schema
    UpdateSchemaParams:
      type: object
      description: Parameters for updating a draft schema
      properties:
        name:
          type: string
          description: Display name for the schema
          example: Updated Employee Badge
        subject_schema:
          type: object
          description: JSON Schema for credential claims
          example:
            type: object
            properties:
              name:
                type: string
              employee_id:
                type: string
              department:
                type: string
            required:
            - name
            - employee_id
        supported_formats:
          type: array
          items:
            type: string
            enum:
            - jwt_vc
            - sd_jwt_vc
            - mdoc
            - data_integrity
          description: Supported credential formats
          example:
          - jwt_vc
          - sd_jwt_vc
        data_integrity_config:
          "$ref": "#/components/schemas/DataIntegrityConfig"
    OpenBadgeSchemaExample:
      type: object
      description: 'Example: Creating an Open Badges 3.0 schema. Note: SD-JWT VC format
        is NOT supported for OB 3.0.'
      example:
        name: Web Development Badge
        credential_type: OpenBadgeCredential
        schema_type: open_badge
        json_ld_context:
        - https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json
        supported_formats:
        - jwt_vc
        - data_integrity
        subject_schema:
          type: object
          properties:
            type:
              type: string
              const: AchievementSubject
            achievement:
              type: object
              properties:
                id:
                  type: string
                  format: uri
                type:
                  type: string
                  const: Achievement
                name:
                  type: string
                description:
                  type: string
                achievementType:
                  type: string
              required:
              - type
              - name
          required:
          - type
          - achievement
    OpenBadgeCredentialExample:
      type: object
      description: 'Example: Issuing an Open Badges 3.0 credential'
      example:
        schema_id: web-development-badge
        subject_identifier: student@example.edu
        subject_identifier_type: email
        claims:
          type: AchievementSubject
          achievement:
            type: Achievement
            name: Web Development Fundamentals
            description: Demonstrated proficiency in HTML, CSS, and JavaScript
            achievementType: DigitalBadge
    VerifyCredentialParams:
      type: object
      description: Parameters for verifying a credential
      properties:
        uuid:
          type: string
          format: uuid
          description: Credential UUID to verify
          example: 8fb9117f-6767-4b79-8ee1-855952f1e98a
        jwt:
          type: string
          description: Credential JWT to verify (alternative to uuid)
          example: eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lzc3Vlci5leGFtcGxlLmNvbSJ9.signature
        skip_status_check:
          type: boolean
          description: Skip revocation/suspension check
          example: false
        skip_expiration_check:
          type: boolean
          description: Skip expiration check
          example: false
        skip_signature_check:
          type: boolean
          description: Skip cryptographic signature check
          example: false
    CreateRenderTemplateParams:
      type: object
      description: Parameters for creating a render template
      properties:
        name:
          type: string
          description: Human-readable template name
          example: Employee Badge Card
        description:
          type: string
          description: Description of the template
          example: Visual template for employee badge credentials
        render_suite:
          type: string
          enum:
          - svg_mustache
          - pdf_mustache
          description: Template rendering engine
          example: svg_mustache
        content:
          type: string
          description: Template content (SVG or HTML)
          example: <svg xmlns="http://www.w3.org/2000/svg"><text>{{name}}</text></svg>
      required:
      - name
      - render_suite
      - content
    UpdateRenderTemplateParams:
      type: object
      description: Parameters for updating a render template
      properties:
        name:
          type: string
          description: Human-readable template name
          example: Updated Employee Badge Card
        description:
          type: string
          description: Description of the template
          example: Updated visual template with new branding
        content:
          type: string
          description: Template content (SVG or HTML)
          example: <svg xmlns="http://www.w3.org/2000/svg"><text>{{name}} - {{department}}</text></svg>
    ValidateRenderTemplateParams:
      type: object
      description: Parameters for validating a render template
      properties:
        render_suite:
          type: string
          enum:
          - svg_mustache
          - pdf_mustache
          description: Template rendering engine
          example: svg_mustache
        content:
          type: string
          description: Template content to validate
          example: <svg xmlns="http://www.w3.org/2000/svg"><text>{{name}}</text></svg>
      required:
      - render_suite
      - content
    DcApiSession:
      type: object
      description: A DC API session for thin client credential verification
      properties:
        session_id:
          type: string
          format: uuid
          description: Unique identifier for the session
          example: cc5c6970-31d8-46af-af18-0e0b991d44b0
        status:
          type: string
          enum:
          - pending
          - processing
          - completed
          - failed
          example: pending
          description: |-
            Current status of the session:
            - pending: Awaiting wallet response
            - processing: Verification in progress
            - completed: Verification succeeded
            - failed: Verification failed
        verified:
          type: boolean
          description: Whether verification succeeded (only present when completed)
          example: true
        trusted:
          type: boolean
          description: Whether the credential comes from a trusted issuer
          example: true
        claims:
          type: object
          additionalProperties: true
          nullable: true
          description: Verified claims from the credential (only when completed)
          example:
            given_name: Jane
            family_name: Doe
            age_over_21: true
        issuer:
          type: object
          nullable: true
          description: Issuer information (only when completed)
          properties:
            name:
              type: string
              description: Issuer name
              example: State DMV
            did:
              type: string
              description: Issuer DID
              example: did:web:dmv.state.gov
            domain:
              type: string
              nullable: true
              example: dmv.state.gov
            domain_fully_verified:
              type: boolean
              example: true
        document_type:
          type: string
          nullable: true
          description: Document type identifier (e.g., org.iso.18013.5.1.mDL for Mobile
            Driver's License)
          example: org.iso.18013.5.1.mDL
        expires_at:
          type: string
          format: date-time
          description: When the session expires
          example: '2026-01-15T10:05:00Z'
        created_at:
          type: string
          format: date-time
          description: When the session was created
          example: '2026-01-15T10:00:00Z'
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: When verification completed (only when completed)
          example: '2026-01-15T10:01:30Z'
        render_url:
          type: string
          format: uri
          nullable: true
          description: Signed URL to render the credential visually (only when completed
            with claims)
          example: https://js.aho.com/v1/sessions/abc123/render?sig=xyz789
    DcApiSessionCreateResponse:
      type: object
      description: Response from creating a DC API session
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            session_id:
              type: string
              format: uuid
              description: Session identifier for subsequent verify call
              example: f0a3a392-9c8e-416e-a71a-628aef39d268
            expires_at:
              type: string
              format: date-time
              description: Session expiration time
              example: '2026-01-15T10:05:00Z'
            created_at:
              type: string
              format: date-time
              description: Session creation time
              example: '2026-01-15T10:00:00Z'
            request:
              type: object
              description: Protocol-specific request configurations
              properties:
                openid4vp:
                  type: object
                  description: Chrome/Android Digital Credentials API request config
                  properties:
                    protocol:
                      type: string
                      example: openid4vp-v1-unsigned
                    data:
                      type: object
                      description: OpenID4VP request object
                      properties:
                        nonce:
                          type: string
                        response_type:
                          type: string
                          example: vp_token
                        response_mode:
                          type: string
                          example: dc_api
                        dcql_query:
                          type: object
                          additionalProperties: true
                        client_metadata:
                          type: object
                          additionalProperties: true
                apple_mdoc:
                  type: object
                  description: Safari/iOS Digital Credentials API request config
                  properties:
                    protocol:
                      type: string
                      example: org-iso-mdoc
                    data:
                      type: object
                      description: CBOR-encoded request data
                      properties:
                        deviceRequest:
                          type: string
                          description: Base64-encoded CBOR deviceRequest
                        encryptionInfo:
                          type: string
                          description: Base64-encoded CBOR encryptionInfo
          required:
          - session_id
          - expires_at
          - created_at
          - request
      required:
      - success
      - data
    DcApiSessionVerifyResponse:
      type: object
      description: Response from verifying a DC API session
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            session_id:
              type: string
              format: uuid
              example: '09803c91-9161-472a-98da-97bc48c625cf'
            verified:
              type: boolean
              description: Whether credential verification succeeded
              example: true
            trusted:
              type: boolean
              description: Whether the credential is from a trusted issuer
              example: true
            claims:
              type: object
              additionalProperties: true
              description: Verified claims from the credential
              example:
                given_name: Jane
                family_name: Doe
                age_over_21: true
            issuer:
              type: object
              nullable: true
              properties:
                name:
                  type: string
                  example: State DMV
                did:
                  type: string
                  example: did:web:dmv.state.gov
                domain:
                  type: string
                  nullable: true
                  example: dmv.state.gov
                domain_fully_verified:
                  type: boolean
                  example: true
            cached:
              type: boolean
              description: True if this is a cached result from a previously completed
                session (idempotent)
              example: false
            render_url:
              type: string
              format: uri
              nullable: true
              description: Signed URL to render the credential visually as SVG/PDF/HTML
              example: https://js.aho.com/v1/sessions/abc123/render?sig=xyz789
            document_type:
              type: string
              nullable: true
              description: Document type identifier (e.g., org.iso.18013.5.1.mDL for
                Mobile Driver's License)
              example: org.iso.18013.5.1.mDL
          required:
          - session_id
          - verified
          - trusted
          - claims
      required:
      - success
      - data
    CreateDcSessionParams:
      type: object
      description: Parameters for creating a DC API session
      properties:
        claims:
          type: array
          items:
            type: string
          description: Claims to request from the credential
          example:
          - given_name
          - family_name
          - age_over_21
        return_claims:
          oneOf:
          - type: boolean
          - type: string
            enum:
            - all
          - type: array
            items:
              type: string
          description: Which claims to return in the result. true=all requested (default),
            false=none, 'all'=all, array=specific claims
          example: true
        document_types:
          type: array
          items:
            type: string
          description: Document types to accept (e.g., org.iso.18013.5.1.mDL)
          example:
          - org.iso.18013.5.1.mDL
        client_name:
          type: string
          description: Display name shown in the wallet (optional, defaults to account
            name)
          example: Acme Bar & Grill
    VerifyDcSessionParams:
      type: object
      description: Parameters for verifying a DC API session
      properties:
        response:
          type: string
          description: The encrypted response from navigator.credentials.get()
          example: eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkEyNTZHQ00iLCJraWQiOiIuLi4ifQ...
        origin:
          type: string
          description: The origin where the credential was requested (for session
            transcript)
          example: https://example.com
      required:
      - response
    RenderParams:
      type: object
      description: Parameters for rendering claims as a visual credential
      properties:
        template:
          type: string
          description: Built-in template key (e.g., mdl_default). Either template
            or render_method required.
          example: mdl_default
        render_method:
          type: object
          description: W3C renderMethod object. Either template or render_method required.
          properties:
            type:
              type: string
              example: TemplateRenderMethod
            renderSuite:
              type: string
              example: svg-mustache
            template:
              type: string
              description: Template URL or data URI
            digestMultibase:
              type: string
              description: Hash for verification
        claims:
          type: object
          additionalProperties: true
          description: Claims to render
          example:
            given_name: Jane
            family_name: Doe
            age_over_21: true
        format:
          type: string
          enum:
          - svg
          - pdf
          - html
          description: 'Output format (default: svg). Ignored when using render_method.'
          example: svg
      required:
      - claims
    RenderResponse:
      type: object
      description: Rendered credential response
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            format:
              type: string
              enum:
              - svg
              - pdf
              - html
              description: Output format
              example: svg
            content:
              type: string
              description: Rendered content (SVG/HTML inline, PDF as base64)
              example: "<svg>...</svg>"
            template:
              type: object
              properties:
                key:
                  type: string
                  description: Template identifier
                  example: mdl_default
                source:
                  type: string
                  enum:
                  - built_in
                  - render_method
                  example: built_in
                verified:
                  type: boolean
                  nullable: true
                  description: Whether template hash was verified
          required:
          - format
          - content
          - template
      required:
      - success
      - data
