audiopod-ai Webhooks API

The webhooks API from audiopod-ai — 5 operation(s) for webhooks.

Operations 8

GET /api/v1/webhooks/endpoints List Endpoints #
POST /api/v1/webhooks/endpoints Create Endpoint #
GET /api/v1/webhooks/endpoints/{endpoint_id} Get Endpoint #
PATCH /api/v1/webhooks/endpoints/{endpoint_id} Update Endpoint #
DELETE /api/v1/webhooks/endpoints/{endpoint_id} Delete Endpoint #
GET /api/v1/webhooks/endpoints/{endpoint_id}/deliveries List Deliveries #
POST /api/v1/webhooks/endpoints/{endpoint_id}/test Send Test Event #
POST /api/v1/webhooks/deliveries/{delivery_id}/redeliver Redeliver #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/audiopod-ai:audiopod-ai-webhooks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

audiopod-ai-webhooks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: AudioPod AI Webhooks API
  description: '# AudioPod AI APIs


    ## Overview


    The AudioPod AI API provides advanced audio processing, AI-powered music generation, voice cloning, transcription, and audio publishing services over a versioned REST interface, with API-key authentication, typed error responses, and published rate limits. ## Base URL

    ```

    https://api.audiopod.ai/api/v1

    ```


    ## Authentication


    ### API Key Authentication (Recommended)

    Most API endpoints use API key authentication. Include your key in the header:

    ```

    X-API-Key: ap_your_api_key

    ```


    ### JWT Token Authentication

    For session-based access (web applications), obtain a token via `/auth/token`:

    ```

    Authorization: Bearer

    ```


    ### Public Endpoints

    Some endpoints like newsletter subscription, health checks, and shared content don''t require authentication. ## Versioning & Deprecation Policy


    The API is versioned **in the URL path**. The current version is `v1`, served at

    `https://api.audiopod.ai/api/v1`. Integrate against an explicit version — never

    against an unversioned path. - **Additive changes ship in place.** New endpoints, new optional request

    fields, and new response fields can appear in `v1` at any time. Clients must

    ignore unknown response fields rather than failing on them. - **Breaking changes ship as a new path version** (`/api/v2`). A breaking change

    is: removing or renaming a field or endpoint, changing a field''s type, adding a

    required request field, or changing the meaning of an existing value. - **Retirement is announced on the wire.** When an endpoint or version is

    scheduled for removal, its responses carry:

    - `Deprecation: true` — the endpoint is deprecated as of now. - `Sunset: ` — the date after which it stops responding

    (RFC 8594). - `Link: ; rel="successor-version"` — where to migrate to. - **Minimum notice: 6 months** between the first `Sunset` header and removal, for

    any endpoint outside a `dev`/preview tag. - Deprecated operations are also marked `"deprecated": true` in this

    specification, so a generated client can surface the warning at build time. ## Rate Limiting


    Limits are applied per API key (falling back to client IP for unauthenticated

    requests) and **scale with subscription tier** — higher tiers get proportionally

    more headroom on the same routes. Indicative baselines for the free tier:


    - **Standard**: 100 requests/minute

    - **Auth endpoints**: 10 requests/minute

    - **Upload endpoints**: 20 requests/minute

    - **Music generation**: `50/minute`

    - **Music retake**: `10/minute`

    - **Music repaint / extend / edit**: `3/minute`


    Do not hard-code these numbers. **Read the quota off the response headers**,

    which are returned on every rate-limited route (routes with no explicit limit

    send no quota headers — absence means "not throttled here", not "quota

    exhausted"):


    | Header | Meaning |

    |---|---|

    | `RateLimit-Limit` | Requests allowed in the current window |

    | `RateLimit-Remaining` | Requests still available in the current window |

    | `RateLimit-Reset` | Seconds until the window resets |

    | `RateLimit-Policy` | The quota policy, e.g. `100;w=60` |

    | `Retry-After` | On a `429` only: seconds to wait before retrying |


    The legacy `X-RateLimit-Limit` / `-Remaining` / `-Reset` names are still sent

    alongside the standard ones for older clients. On a `429`, back off for at least `Retry-After` seconds. Retries with

    exponential backoff and jitter are expected; tight retry loops are not. ## Errors


    Every `4xx` and `5xx` response uses one typed envelope:


    ```json

    {

    "error": "NOT_FOUND",

    "message": "The requested resource was not found.",

    "status": 404,

    "detail": "..."

    }

    ```


    - `error` — a **stable, machine-readable code**. Branch on this. - `message` — human-readable prose. Do not parse; wording can change. - `status` — the HTTP status, repeated for convenience. - `detail` — the legacy payload, retained for backward compatibility. For a

    `422` it is the array of failing fields. The full shape is published as the `ErrorResponse` schema, and each operation

    below documents the statuses it can return.'
  version: 2.0.0
servers:
- url: https://api.audiopod.ai
  description: Production
security:
- apiKeyAuth: []
- bearerAuth: []
tags:
- name: Webhooks
paths:
  /api/v1/webhooks/endpoints:
    get:
      tags:
      - Webhooks
      summary: List Endpoints
      operationId: list_endpoints
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                items:
                  $ref: '#/components/schemas/WebhookEndpointResponse'
                type: array
                title: Response List Endpoints Api V1 Webhooks Endpoints Get
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
      - OAuth2PasswordBearer: []
      x-original-operation-id: list_endpoints_api_v1_webhooks_endpoints_get
    post:
      tags:
      - Webhooks
      summary: Create Endpoint
      description: Register a webhook endpoint. Returns the signing secret exactly once.
      operationId: create_endpoint
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookEndpointCreate'
        required: true
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointCreateResponse'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
      - OAuth2PasswordBearer: []
      x-original-operation-id: create_endpoint_api_v1_webhooks_endpoints_post
  /api/v1/webhooks/endpoints/{endpoint_id}:
    get:
      tags:
      - Webhooks
      summary: Get Endpoint
      operationId: get_endpoint
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: endpoint_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Endpoint Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointResponse'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: get_endpoint_api_v1_webhooks_endpoints__endpoint_id__get
    patch:
      tags:
      - Webhooks
      summary: Update Endpoint
      operationId: update_endpoint
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: endpoint_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Endpoint Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookEndpointUpdate'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEndpointResponse'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: update_endpoint_api_v1_webhooks_endpoints__endpoint_id__patch
    delete:
      tags:
      - Webhooks
      summary: Delete Endpoint
      operationId: delete_endpoint
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: endpoint_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Endpoint Id
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: delete_endpoint_api_v1_webhooks_endpoints__endpoint_id__delete
  /api/v1/webhooks/endpoints/{endpoint_id}/deliveries:
    get:
      tags:
      - Webhooks
      summary: List Deliveries
      operationId: list_deliveries
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: endpoint_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Endpoint Id
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          maximum: 200
          minimum: 1
          default: 50
          title: Limit
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/WebhookDeliveryResponse'
                title: Response List Deliveries Api V1 Webhooks Endpoints  Endpoint Id  Deliveries Get
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: list_deliveries_api_v1_webhooks_endpoints__endpoint_id__deliveries_get
  /api/v1/webhooks/endpoints/{endpoint_id}/test:
    post:
      tags:
      - Webhooks
      summary: Send Test Event
      description: Deliver a synthetic signed event so the developer can confirm the loop.
      operationId: send_test_event
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: endpoint_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Endpoint Id
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: send_test_event_api_v1_webhooks_endpoints__endpoint_id__test_post
  /api/v1/webhooks/deliveries/{delivery_id}/redeliver:
    post:
      tags:
      - Webhooks
      summary: Redeliver
      description: Re-dispatch a failed/dead delivery (ownership checked via its endpoint).
      operationId: redeliver
      security:
      - OAuth2PasswordBearer: []
      parameters:
      - name: delivery_id
        in: path
        required: true
        schema:
          type: string
          format: uuid
          title: Delivery Id
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-original-operation-id: redeliver_api_v1_webhooks_deliveries__delivery_id__redeliver_post
components:
  schemas:
    WebhookEndpointCreate:
      properties:
        url:
          type: string
          title: Url
          description: https URL we POST events to
        events:
          items:
            type: string
          type: array
          title: Events
          description: Event types to subscribe to (job.completed, job.failed, job.cancelled, narration.review_required, audiobook.cast.detected)
        description:
          anyOf:
          - type: string
          - type: 'null'
          title: Description
      type: object
      required:
      - url
      title: WebhookEndpointCreate
    InsufficientCreditsDetail:
      type: object
      title: InsufficientCreditsDetail
      description: 'Everything needed to resolve a credit shortfall: what the job costs, what the account holds, and the ways to add more.'
      properties:
        error:
          type: string
          description: Always `INSUFFICIENT_CREDITS` on this response.
          examples:
          - INSUFFICIENT_CREDITS
        message:
          type: string
          description: Human-readable explanation. Do not parse.
        credits_required:
          type:
          - integer
          - 'null'
          description: Credits this job needs. Null when the shortfall was detected without a priced estimate — show no figure rather than a wrong one.
        credits_available:
          type: integer
          description: 'Total spendable credits: subscription plus pay-as-you-go.'
        subscription_credits:
          type: integer
          description: Plan credits remaining in the current cycle.
        payg_credits:
          type: integer
          description: Pay-as-you-go credits, which never expire.
        current_plan:
          type: string
          examples:
          - Basic
        upgrade_options:
          type: array
          description: Plans above the current one, cheapest first.
          items:
            type: object
            properties:
              plan:
                type: string
              price:
                type: string
              credits:
                type: string
              annual:
                type: string
        payg_option:
          type: object
          description: Where to buy credits that never expire.
          properties:
            description:
              type: string
            url:
              type: string
        upgrade_url:
          type: string
          examples:
          - /pricing
        auto_refill:
          type: object
          description: Whether an automatic top-up is handling this shortfall. `off` means none is running and the caller should top up or upgrade; `pending` means one is in flight, so poll the balance and retry the same request; `failed` means one was attempted and did not complete; `ineligible` means automatic top-up cannot run for this account.
          properties:
            state:
              type: string
              enum:
              - 'off'
              - pending
              - failed
              - ineligible
          required:
          - state
        upload_ref:
          type:
          - string
          - 'null'
          description: Reference to the input already uploaded for this request, when there was one, so a retry after topping up does not have to send the file again. Null when the request carried no upload.
      required:
      - error
      - message
      - credits_available
      - current_plan
    InsufficientCreditsResponse:
      type: object
      title: InsufficientCreditsResponse
      description: Error envelope for a credit shortfall. Identical to ErrorResponse except that `detail` is the typed InsufficientCreditsDetail object.
      properties:
        code:
          type: string
          description: Stable machine-readable code. **Branch on this field.**
          examples:
          - PAYMENT_REQUIRED
        error:
          type: string
          examples:
          - PAYMENT_REQUIRED
        message:
          type: string
          description: Human-readable explanation. Do not parse.
        status:
          type: integer
          examples:
          - 402
        detail:
          $ref: '#/components/schemas/InsufficientCreditsDetail'
      required:
      - code
      - message
      - status
    WebhookDeliveryResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        event_id:
          type: string
          format: uuid
          title: Event Id
        event_type:
          type: string
          title: Event Type
        status:
          type: string
          title: Status
        attempts:
          type: integer
          title: Attempts
        last_response_code:
          anyOf:
          - type: integer
          - type: 'null'
          title: Last Response Code
        last_error:
          anyOf:
          - type: string
          - type: 'null'
          title: Last Error
        next_retry_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Next Retry At
        created_at:
          type: string
          format: date-time
          title: Created At
        delivered_at:
          anyOf:
          - type: string
            format: date-time
          - type: 'null'
          title: Delivered At
      type: object
      required:
      - id
      - event_id
      - event_type
      - status
      - attempts
      - created_at
      title: WebhookDeliveryResponse
    ErrorResponse:
      type: object
      title: ErrorResponse
      description: Standard error envelope. Every 4xx and 5xx response from the AudioPod AI API carries `code`, `message` and `status`. Branch on `code` — a stable machine-readable string — rather than parsing `message`, which is human-facing prose and may be reworded at any time. `detail` and `error` are retained for backward compatibility with older integrations, and their shapes vary by endpoint.
      properties:
        code:
          type: string
          description: Stable machine-readable error code, present on every error response. **Branch on this field.** Values are additive and existing codes are not renamed.
          examples:
          - NOT_FOUND
          - AUTHENTICATION_REQUIRED
          - RATE_LIMIT_EXCEEDED
        error:
          description: Legacy error field. Usually the same string as `code`, but a few older endpoints emit an object here instead (`code` / `message` / `details`). Prefer `code`, which is always a string.
          examples:
          - NOT_FOUND
          - AUTHENTICATION_REQUIRED
        message:
          type: string
          description: Human-readable explanation. Do not parse.
          examples:
          - The requested resource was not found.
        status:
          type: integer
          description: HTTP status code, repeated in the body for convenience.
          examples:
          - 404
        detail:
          description: Legacy detail payload, preserved verbatim for backward compatibility. A string for most errors, an array of field errors for validation failures, an object for auth failures.
      required:
      - code
      - message
      - status
    WebhookEndpointCreateResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        url:
          type: string
          title: Url
        events:
          items:
            type: string
          type: array
          title: Events
        active:
          type: boolean
          title: Active
        description:
          anyOf:
          - type: string
          - type: 'null'
          title: Description
        created_at:
          type: string
          format: date-time
          title: Created At
        secret:
          type: string
          title: Secret
          description: Signing secret — shown once, store it now
      type: object
      required:
      - id
      - url
      - events
      - active
      - created_at
      - secret
      title: WebhookEndpointCreateResponse
      description: Returned ONLY at creation — carries the raw signing secret exactly once.
    WebhookEndpointUpdate:
      properties:
        url:
          anyOf:
          - type: string
          - type: 'null'
          title: Url
        events:
          anyOf:
          - items:
              type: string
            type: array
          - type: 'null'
          title: Events
        active:
          anyOf:
          - type: boolean
          - type: 'null'
          title: Active
        description:
          anyOf:
          - type: string
          - type: 'null'
          title: Description
      type: object
      title: WebhookEndpointUpdate
    WebhookEndpointResponse:
      properties:
        id:
          type: string
          format: uuid
          title: Id
        url:
          type: string
          title: Url
        events:
          items:
            type: string
          type: array
          title: Events
        active:
          type: boolean
          title: Active
        description:
          anyOf:
          - type: string
          - type: 'null'
          title: Description
        created_at:
          type: string
          format: date-time
          title: Created At
      type: object
      required:
      - id
      - url
      - events
      - active
      - created_at
      title: WebhookEndpointResponse
  headers:
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
    RateLimitLimit:
      description: Request quota for the current window on this route.
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
    RateLimitReset:
      description: Seconds until the current window resets.
      schema:
        type: integer
    RateLimitPolicy:
      description: Quota policy for this route, e.g. `100;w=60`. Limits scale with subscription tier.
      schema:
        type: string
  responses:
    BadRequest:
      description: Bad request — malformed syntax or an invalid parameter combination.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    PaymentRequired:
      description: 'Not enough credits to run this job. `detail` carries the typed InsufficientCreditsDetail object: what the job costs, what the account holds, and how to add more.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InsufficientCreditsResponse'
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Authenticated, but not permitted (wrong scope, or a plan-gated feature).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: Temporarily unavailable. Safe to retry with backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Authentication required or the supplied credential is invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: Rate limit exceeded. Honour `Retry-After` before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      headers:
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
        RateLimit-Policy:
          $ref: '#/components/headers/RateLimitPolicy'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
    NotFound:
      description: The requested resource does not exist.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Conflict:
      description: Conflict with the current state of the resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ValidationFailed:
      description: Request validation failed. `detail` lists the offending fields.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    OAuth2PasswordBearer:
      type: oauth2
      flows:
        password:
          scopes: {}
          tokenUrl: /api/v1/auth/token
    OptionalOAuth2Scheme:
      type: oauth2
      flows:
        password:
          scopes: {}
          tokenUrl: /api/v1/auth/token
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'AudioPod API key. Create one in the dashboard under API Keys and send it as `X-API-Key: ap_...`. This is the recommended method for server-to-server and agent integrations.'
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Session token obtained from `/api/v1/auth/token`. Intended for first-party web sessions; prefer an API key for integrations.