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

# Update an automation's status

> Pauses (`paused`) or resumes (`active`) an automation. The body accepts
only these two values; any other value returns `400 invalid_request`.
The body accepts no other field: an unknown field (a typo such as
`statut`) returns `400 invalid_request` with the field name in
`details.parameter`, so a request that would change nothing is never
silently accepted.

- **Idempotent**: asking for the status the automation already has
  returns `200` and changes nothing (no event is sent).
- **Not controllable**: an automation in `draft` or `error` returns
  `422 automation_not_controllable` (`details.status`). It has to be
  activated or repaired in the Agentova app first.
- **One mailbox, one agent**: resuming an e-mail automation whose
  mailbox is already used by another active agent returns
  `422 automation_not_controllable` with `details.reason:
  account_in_use`, as in the Agentova app.
- **Response time**: the response is sent within 8 seconds. Resuming
  can take longer, because the channel has to be reconnected: the
  response then carries the current status, the work goes on in the
  background, and the final status is announced by an
  `automation.status_changed` event. If the channel cannot be
  reconnected, the automation ends in `error` (in the response or in
  that event) and has to be resumed from the Agentova app.

What a pause does depends on the channel. Except for Customer.io after
a short pause (see below), nothing that arrives during the pause is
caught up after the resume.

- **E-mail** (Gmail, Outlook, IMAP): pausing stops listening to the
  mailbox, exactly like the switch in the Agentova app, unless another
  active agent uses the same mailbox. E-mails received during the pause
  never get a reply from this automation. Resuming reconnects the
  mailbox and only handles the e-mails that arrive after the resume.
- **Meta messages, WhatsApp, comments and stories**: everything that
  arrives during the pause is ignored.
- **Lead Ads**: leads keep being recorded in Agentova and announced by
  `lead.created`. Only the automation's own actions (message, e-mail,
  call…) are skipped during the pause, and they are not run later.
- **CRM sources**: pausing removes the trigger that listens to the CRM,
  and resuming sets it up again; CRM events that occur during the
  pause are never replayed. For Customer.io, which Agentova reads
  every 15 minutes, a paused automation is not read. After a pause of
  more than 6 hours, the segment changes made during the pause are
  never replayed; after a shorter pause, they may be handled when the
  automation resumes.




## OpenAPI

````yaml /openapi/openapi-v1.yaml patch /automations/{id}
openapi: 3.0.3
info:
  title: Agentova Public API
  version: 1.0.0
  termsOfService: https://agentova.ai/legal/terms-of-use
  license:
    name: Proprietary — Agentova terms of use
    url: https://agentova.ai/legal/terms-of-use
  contact:
    name: Agentova support
    email: contact@agentova.ai
    url: https://docs.agentova.ai
  description: >
    The Agentova Public API lets your own code, Zapier or n8n work with an

    Agentova workspace: read its automations, runs and leads, pause and resume

    its automations, and receive events through signed webhooks.



    ## Base URL and authentication


    All endpoints are served over HTTPS under `https://core-api.agentova.ai/v1`.

    Every request carries an API key, created in the Agentova app

    (Settings → API), in the `Authorization` header:

    `Authorization: Bearer agk_live_…`


    - A key belongs to one workspace and gives access to the whole workspace.
      The key identifies the workspace: no workspace identifier is ever sent.
    - Every key starts with `agk_live_`. There are no test keys and no separate
      test environment: to experiment safely, use a dedicated workspace.
    - A revoked key is refused immediately, on every endpoint.

    - The API is meant to be called from a server. It sends no CORS headers,
      so a web page cannot call it from a browser, and an `OPTIONS` request
      receives an error in the format described under Errors.


    ## Stability


    This is version 1.0.0 of the v1 API, and v1 is stable: no breaking change

    will be made under `/v1`. Additive changes can still happen: new optional

    fields, new event types, new enum values. Your client must ignore the

    fields, event types and enum values it does not know.



    ## Coverage


    - **Automations**: the messaging automations of the workspace on Meta
      networks (`facebook`, `instagram`, `instagram_page`), WhatsApp
      (`whatsapp`) and e-mail (`gmail`, `microsoft_outlook`, `imap`), with the
      types `social_comments`, `social_story`, `social_messages`, `lead_ads`
      and `email_messages`, plus the CRM sources (`crm_source`). They can all
      be read, and paused or resumed with `PATCH`.
    - **Leads**: from the sources `widget`, `lead_ads`, `telephony`, `social`
      and `crm`.
    - **Runs**: see the `Run` schema for the automations that produce runs.

    - **Webhook events**: `lead.created`, `run.completed` and
      `automation.status_changed`.


    ## Conventions


    - **Identifiers** are opaque strings prefixed by their type: `aut_`
      (automation), `agt_` (agent), `run_` (run), `lea_` (lead), `whk_`
      (webhook subscription), `evt_` (event). Store them and send them back
      unchanged; never validate or parse them (length, alphabet). They are not
      UUIDs.
    - **Dates** are ISO 8601, in UTC, with the `Z` suffix.

    - **Unknown query parameters** are ignored, never rejected, so that a
      client written for a later version keeps working.
    - **Request bodies** are JSON, sent with `Content-Type: application/json`,
      and limited to 16 KB. Another content type is refused with HTTP `415`,
      a larger body with HTTP `413`, both with the code `invalid_request`.
    - **Caching**: every response carries `Cache-Control: no-store`, because
      responses contain personal data.


    ## Pagination


    Lists are paginated with an opaque cursor. `limit` takes a value from 1 to

    100 (25 by default); a value out of range is refused with `400`, not

    corrected. A page looks like

    `{ "data": [...], "has_more": true, "next_cursor": "..." }`: to get the

    next page, send `next_cursor` back as `cursor`. A missing or empty

    `cursor`, or the literal word `null`, means the first page.

    `GET /webhooks` is not paginated.



    ## Rate limits


    - Each API key can make about 100 requests per minute. Requests are
      counted per server instance, so this limit is approximate.
    - Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and
      `X-RateLimit-Reset` (seconds until the window resets, not a timestamp),
      `401` and `403` responses included.
    - Above the limit, the API answers `429 rate_limited` with a `Retry-After`
      header, in seconds.
    - More than 30 authentication failures per minute from the same IP address
      also lead to `429`. This never applies to requests made with a valid
      key.


    ## Errors


    Every 4xx and 5xx response has the same body:

    `{ "error": { "code": "...", "message": "...", "details": {} } }`.


    - `code` is stable and comes from a closed list (`ErrorCode`): branch on
      it.
    - `message` is in English, meant to be shown to a person, and can change
      at any time.
    - `details` is always an object: empty, or giving context such as the
      faulty `parameter` and a `reason`.

    | HTTP status | `code` | Meaning |

    |---|---|---|

    | 400 | `invalid_request` | Invalid query parameter or body
    (`details.parameter`) |

    | 413, 415 | `invalid_request` | Body larger than 16 KB, or unsupported
    content type (`details.reason`) |

    | 401 | `invalid_api_key` | Missing, malformed, unknown or revoked key |

    | 403 | `workspace_access_denied` | The workspace's subscription does not
    allow API access |

    | 404 | `automation_not_found` | No such automation in this workspace |

    | 404 | `webhook_not_found` | No such webhook subscription in this workspace
    |

    | 404 | `route_not_found` | Unknown path or method under `/v1` (never `405`)
    |

    | 422 | `automation_not_controllable` | `PATCH` on an automation in `draft`
    or `error` (`details.status`), or resuming an e-mail automation whose
    mailbox another active agent already uses (`details.reason: account_in_use`)
    |

    | 429 | `rate_limited` | Rate limit exceeded: wait `Retry-After` seconds |

    | 500 | `internal_error` | Unexpected error (generic message) |

    | 503 | `service_unavailable` | The API is temporarily switched off by
    Agentova: retry later |



    ## Webhooks


    Create a subscription with `POST /webhooks`. Agentova then sends every

    event of the subscribed types as a `POST` request to your URL; the body is

    described by the `delivery` callback of `POST /webhooks`.


    - **Request**: a `POST` with `Content-Type: application/json` and
      `User-Agent: Agentova-Webhooks/1.0`.
    - **Signature**: each delivery carries
      `X-Agentova-Signature: t=<unix timestamp>,v1=<hex digest>`. The digest
      is the HMAC-SHA256 of the string `{t}.{raw request body}`, keyed with the
      complete subscription `secret`, `whsec_` prefix included. Compare digests
      in constant time, and reject a delivery whose `t` is more than 5 minutes
      away from your clock (recommended tolerance). The official Zapier app
      accepts 1 hour, because Zapier can process hooks late and the hook URL
      is itself a secret.
    - **Success** is a 2xx status received within 10 seconds (a deadline for
      the whole response). The response body is ignored. Redirects are not
      followed: a 3xx is a failure.
    - **Retries**: 8 attempts spread over about 27 hours 35 minutes. The first
      attempt is immediate; after each failure, the next one comes 5 seconds,
      5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours and finally 10 hours
      later. When your endpoint answers `429` or `503` with a `Retry-After`
      header, the next attempt waits at least that long, up to 12 hours. No
      attempt is ever scheduled more than 36 hours after the event was
      created: when the next one would be, the delivery is abandoned.
    - **`410 Gone`** deletes the subscription immediately, without any
      notification: answer `410` to unsubscribe (this is how Zapier reports a
      deleted Zap).
    - **Disabling**: a delivery is abandoned after its 8th failed attempt, or
      earlier when it reaches the 36-hour limit. The
      subscription is then disabled if it has at least 3 abandoned deliveries
      in a row and has been failing without interruption for at least 72
      hours. It is also disabled at once, without any delivery, if its URL no
      longer passes the address checks (an IP address that became forbidden).
      Workspace admins are notified in the app and by push
      notification. A disabled subscription receives nothing and cannot be
      re-enabled: delete it and create a new one (Zapier: turn the Zap off and
      on again; n8n: deactivate and reactivate the workflow). Disabled
      subscriptions are deleted automatically 30 days after being disabled.
    - **At least once, in no guaranteed order**: the same event can be
      delivered more than once, and events can arrive out of order.
      Deduplicate on the event `id` (`evt_…`): it is the same on every attempt
      and for every subscription that receives the event; keep the ids you
      have seen for at least 48 hours: retries are always scheduled within 36
      hours of the event's creation. To order events,
      use the timestamp of the resource in `data` (`updated_at` of an
      automation, `created_at` of a lead, `occurred_at` of a run), not the
      arrival order.
    - **Ownership**: subscriptions belong to the workspace; workspace admins
      see and delete them in Settings → API. Revoking the key that created a
      subscription deletes the subscription as well, unless the admin unticks
      that option in Settings → API. A key is also revoked, with its
      subscriptions, when the admin who created it leaves the workspace,
      loses the admin role or deletes their account.
    - **Retention**: the webhook delivery log is kept for 30 days, and runs
      for 90 days.
    - **While the API is switched off** (`503 service_unavailable`), no
      delivery is created for the events that happen in the meantime, and the
      deliveries already in progress are suspended: they resume when the API
      is back. Catch up on the missed events with the list endpoints.


    ## Support


    Documentation: https://docs.agentova.ai. Contact: contact@agentova.ai.
servers:
  - url: https://core-api.agentova.ai/v1
    description: Production, the only environment (there is no separate test environment)
security:
  - bearerAuth: []
paths:
  /automations/{id}:
    patch:
      summary: Update an automation's status
      description: |
        Pauses (`paused`) or resumes (`active`) an automation. The body accepts
        only these two values; any other value returns `400 invalid_request`.
        The body accepts no other field: an unknown field (a typo such as
        `statut`) returns `400 invalid_request` with the field name in
        `details.parameter`, so a request that would change nothing is never
        silently accepted.

        - **Idempotent**: asking for the status the automation already has
          returns `200` and changes nothing (no event is sent).
        - **Not controllable**: an automation in `draft` or `error` returns
          `422 automation_not_controllable` (`details.status`). It has to be
          activated or repaired in the Agentova app first.
        - **One mailbox, one agent**: resuming an e-mail automation whose
          mailbox is already used by another active agent returns
          `422 automation_not_controllable` with `details.reason:
          account_in_use`, as in the Agentova app.
        - **Response time**: the response is sent within 8 seconds. Resuming
          can take longer, because the channel has to be reconnected: the
          response then carries the current status, the work goes on in the
          background, and the final status is announced by an
          `automation.status_changed` event. If the channel cannot be
          reconnected, the automation ends in `error` (in the response or in
          that event) and has to be resumed from the Agentova app.

        What a pause does depends on the channel. Except for Customer.io after
        a short pause (see below), nothing that arrives during the pause is
        caught up after the resume.

        - **E-mail** (Gmail, Outlook, IMAP): pausing stops listening to the
          mailbox, exactly like the switch in the Agentova app, unless another
          active agent uses the same mailbox. E-mails received during the pause
          never get a reply from this automation. Resuming reconnects the
          mailbox and only handles the e-mails that arrive after the resume.
        - **Meta messages, WhatsApp, comments and stories**: everything that
          arrives during the pause is ignored.
        - **Lead Ads**: leads keep being recorded in Agentova and announced by
          `lead.created`. Only the automation's own actions (message, e-mail,
          call…) are skipped during the pause, and they are not run later.
        - **CRM sources**: pausing removes the trigger that listens to the CRM,
          and resuming sets it up again; CRM events that occur during the
          pause are never replayed. For Customer.io, which Agentova reads
          every 15 minutes, a paused automation is not read. After a pause of
          more than 6 hours, the segment changes made during the pause are
          never replayed; after a shorter pause, they may be handled when the
          automation resumes.
      operationId: updateAutomationStatus
      parameters:
        - $ref: '#/components/parameters/AutomationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - status
              additionalProperties: false
              properties:
                status:
                  type: string
                  description: |
                    `paused` to pause the automation, `active` to resume it.
                  enum:
                    - active
                    - paused
            example:
              status: paused
      responses:
        '200':
          description: >
            The automation after the request (returned unchanged if it already
            had the requested status). When a resume is still in progress after
            8 seconds, this is the current status; the final one is announced by
            `automation.status_changed`.
          headers:
            Cache-Control:
              $ref: '#/components/headers/Cache-Control'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Automation'
              example:
                id: aut_01HZX3Q8K5N7P2R4S6T8V0W2Y4
                name: Comment replies — Support Agent
                type: social_comments
                provider: instagram_page
                agent_id: agt_01HZX3Q8K5N7P2R4S6T8V0W2Y5
                agent_name: Support Agent
                status: active
                updated_at: '2026-08-21T07:00:00Z'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '422':
          description: >
            Not controllable through the API: the automation is in `draft` or
            `error` (`details.status`), or it is an e-mail automation whose
            mailbox another active agent already uses (`details.reason:
            account_in_use`).
          headers:
            Cache-Control:
              $ref: '#/components/headers/Cache-Control'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                draft_or_error:
                  summary: Draft or error
                  value:
                    error:
                      code: automation_not_controllable
                      message: >-
                        This automation is in draft or in error: activate it
                        from the Agentova app first
                      details:
                        status: draft
                account_in_use:
                  summary: Mailbox used by another agent
                  value:
                    error:
                      code: automation_not_controllable
                      message: >-
                        This mailbox is already used by another active agent:
                        detach it from that agent in the Agentova app first
                      details:
                        status: paused
                        reason: account_in_use
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    AutomationId:
      name: id
      in: path
      required: true
      description: Opaque `aut_…` identifier, as returned by the API.
      schema:
        type: string
  headers:
    Cache-Control:
      description: Always `no-store` (personal data, no intermediate cache)
      schema:
        type: string
        enum:
          - no-store
    X-RateLimit-Limit:
      description: >
        Number of requests allowed per window (per key; per IP address when the
        429 comes from repeated authentication failures)
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current window
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Seconds left before the window resets (NOT a timestamp)
      schema:
        type: integer
  schemas:
    Automation:
      type: object
      description: An automation of the workspace, carried out by one agent.
      required:
        - id
        - name
        - type
        - provider
        - agent_id
        - agent_name
        - status
        - updated_at
      properties:
        id:
          type: string
          description: >-
            Opaque identifier prefixed with `aut_`. Stable for a given
            automation.
        name:
          type: string
          description: >
            Display label in English: what the automation does, then the agent's
            name (for example `Comment replies — Support Agent`, or `HubSpot
            contacts — Support Agent` for a CRM source). For display only: it
            can change, and two automations can share one.
        type:
          $ref: '#/components/schemas/AutomationType'
        provider:
          type: string
          description: >
            The connected service, as a raw value. Messaging automations:
            `facebook`, `instagram`, `instagram_page`, `whatsapp`, `gmail`,
            `microsoft_outlook`, `imap`. CRM sources carry the name of the CRM
            (for example `hubspot`). Treat it as an open string: new values can
            appear.
        agent_id:
          type: string
          description: Opaque identifier of the agent, prefixed with `agt_`.
        agent_name:
          type: string
          description: Name of the agent.
        status:
          $ref: '#/components/schemas/AutomationStatus'
        updated_at:
          type: string
          format: date-time
          description: >
            Date of the last change to the automation. Use it to order
            `automation.status_changed` events.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - details
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
              description: >
                In English, meant to be displayed; it can change without notice
                (branch on `code`).
            details:
              type: object
              description: >
                Empty (`{}`) or context: `parameter`, `allowed`, `max`,
                `reason`, `status`, `retry_after_seconds`…
    AutomationType:
      type: string
      description: >
        `social_comments`, `social_story` and `lead_ads` cover the Meta networks
        (Facebook, Instagram). `social_messages` replies to private messages on
        the Meta networks and on WhatsApp (the `provider` field tells them
        apart). `email_messages` replies to the e-mails of a Gmail, Outlook or
        IMAP mailbox. `crm_source` is an automation triggered by a CRM.
      enum:
        - social_comments
        - social_story
        - social_messages
        - lead_ads
        - email_messages
        - crm_source
    AutomationStatus:
      type: string
      description: |
        - `active`: running.
        - `paused`: paused from the Agentova app or through `PATCH`.
        - `draft`: never activated; it has to be activated from the Agentova
          app.
        - `error`: stopped by a failure that has to be fixed from the Agentova
          app (for example a lost e-mail connection, a channel that could not
          be reconnected on resume, or a subscription to the provider that
          could not be renewed).

        `PATCH` only acts on `active` and `paused` automations.

        An automation that is deleted or deactivated in the Agentova app, or
        whose connected account is disconnected, is no longer returned by the
        API (`404 automation_not_found`). When a failure is what removes it
        (revoked token, mailbox authentication refused, reconnection
        impossible), a last `automation.status_changed` event is sent first,
        with `status: error`. When the account is reconnected, an
        `automation.status_changed` event with `status: active` is sent for
        each automation that comes back. A deliberate deletion sends no event.
      enum:
        - active
        - paused
        - draft
        - error
    ErrorCode:
      type: string
      description: >
        Stable error codes. `invalid_request` (400; also 413 when the body is
        larger than 16 KB and 415 for an unsupported content type: the HTTP
        status is kept and the cause is in `details.reason`) · `invalid_api_key`
        (401) · `workspace_access_denied` (403) · `automation_not_found` (404) ·
        `webhook_not_found` (404) · `route_not_found` (404: unknown path or
        method) · `automation_not_controllable` (422: automation in `draft` or
        `error`, see `details.status`) · `rate_limited` (429) · `internal_error`
        (500, generic message) · `service_unavailable` (503: the API is
        temporarily switched off by Agentova; retry later).
      enum:
        - invalid_request
        - invalid_api_key
        - workspace_access_denied
        - automation_not_found
        - webhook_not_found
        - route_not_found
        - automation_not_controllable
        - rate_limited
        - internal_error
        - service_unavailable
  responses:
    BadRequest:
      description: Invalid query parameter or body (`details.parameter` names it)
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: invalid_request
              message: The limit parameter must be an integer between 1 and 100
              details:
                parameter: limit
                max: 100
    Unauthorized:
      description: >-
        Missing, malformed, unknown or revoked key (deliberately
        indistinguishable)
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: invalid_api_key
              message: Invalid or revoked key — create one in Settings → API
              details: {}
    Forbidden:
      description: >
        Valid key, but the workspace does not have access to the service (or no
        longer has it): its subscription is blocked (unpaid, paused, or initial
        payment never completed). A workspace without a subscription is on the
        free plan and is not affected. This is not a per-key permission: v1 has
        no per-key permissions.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: workspace_access_denied
              message: This workspace's subscription does not allow access to the API
              details: {}
    NotFound:
      description: >
        Not found in this workspace (the same response whether the resource
        exists in another workspace or nowhere), or unknown route
        (`route_not_found`).
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: automation_not_found
              message: Automation not found in this workspace
              details: {}
    PayloadTooLarge:
      description: >
        Request body larger than 16 KB. The code is `invalid_request`; the HTTP
        status stays `413` and `details.reason` gives the cause.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: invalid_request
              message: Invalid request
              details:
                reason: Request body is too large
    UnsupportedMediaType:
      description: >
        Request body not sent as JSON (`Content-Type` other than
        `application/json`). The code is `invalid_request`; the HTTP status
        stays `415` and `details.reason` gives the cause.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: invalid_request
              message: Invalid request
              details:
                reason: Unsupported Media Type
    RateLimited:
      description: >
        Rate limit exceeded: too many requests with this key, or too many
        authentication failures from this IP address
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
        Retry-After:
          description: Seconds to wait before retrying
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded — retry in a few seconds
              details:
                retry_after_seconds: 42
    ServiceUnavailable:
      description: >
        The API is temporarily switched off by Agentova (`service_unavailable`):
        retry later. This response may come without the `X-RateLimit-*` headers.
        While the API is switched off, no webhook delivery is created for the
        events that happen in the meantime.
      headers:
        Cache-Control:
          $ref: '#/components/headers/Cache-Control'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: service_unavailable
              message: The API is temporarily unavailable — retry later
              details: {}
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: agk_live_<32 characters>
      description: >
        API key created in the Agentova app (Settings → API), sent as
        `Authorization: Bearer agk_live_…`. One key = one workspace: the key
        determines the workspace, and no workspace identifier ever travels in
        requests. The `Bearer` scheme is case-insensitive. A revoked key is
        refused immediately.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.