sendraven-ai Approvals API

The Approvals API from sendraven-ai — 2 operation(s) for approvals.

Operations 2

GET /v1/approvals List messages held for human approval #
POST /v1/approvals/{id} Approve or reject a held message #

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/sendraven-ai:sendraven-ai-approvals-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

sendraven-ai-approvals-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Sendraven Ai Approvals API
  version: 1.0.0
  description: 'Operations tagged Approvals across 2 of this provider''s published API definitions: sendraven-ai-api-openapi.json, sendraven-ai-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.sendraven.ai
security:
- bearerAuth: []
tags:
- name: Approvals
paths:
  /v1/approvals:
    get:
      summary: List messages held for human approval
      description: 'A key configured to require approval drafts rather than sends: POST /v1/emails answered 202 with status pending_approval and an approval_id, and the draft waits here. There is nothing to retry. Returns every approval still pending and not expired (they expire 72 hours after the send by default), oldest first. Not paged: limit and cursor are ignored and next_cursor is always null. Every pending approval is returned; has_more is true when there are 500 or more, even though nothing is left out.'
      x-required-scope: emails:read
      responses:
        '200':
          description: Pending approvals with the content to review
          content:
            application/json:
              schema:
                type: object
                required:
                - object
                - data
                - has_more
                - next_cursor
                properties:
                  object:
                    type: string
                    enum:
                    - list
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Approval'
                  has_more:
                    type: boolean
                    description: 'Not paged: true only when the list hit its cap, meaning there is more than this endpoint can return.'
                  next_cursor:
                    type:
                    - string
                    - 'null'
                    description: Always null; this list is not paged.
        '401':
          description: 'unauthorized: no Bearer token, or the key or token is invalid, revoked or expired.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: 'forbidden: the key lacks the emails:read scope. The message names it.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: 'rate_limited: more requests than the per-key rate (600 a minute by default). Wait the seconds in the Retry-After header and retry.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: 'service_unavailable: the API is under heavy load and could not get a database connection in time. Usually nothing was done; a send that was already under way may have been, so check GET /v1/emails before retrying one. Wait the seconds in the Retry-After header.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
      - Approvals
      operationId: getV1Approvals
      x-operation-id-source: derived
    servers:
    - url: https://api.sendraven.ai
  /v1/approvals/{id}:
    post:
      summary: Approve or reject a held message
      description: 'Decides one held send. Only an API key without guardrails that did not make the draft can decide: an OAuth access token, the key that made the draft, and any key with a guardrail (requires_approval, allowed_recipients or a daily_send_limit) are refused with 403 forbidden, so an agent cannot release its own mail, another held agent''s, or mail its own limits would not allow. A person in the dashboard can always decide. Rejecting marks the message canceled. Approving first re-checks suppressions and topic opt-outs for every recipient (dropping anyone who left; if no To address remains nothing is sent, the message is recorded rejected, and the response carries skipped and reason) and the plan allowance. Then, if the draft carried a scheduled_at still in the future, the message is put on that schedule (status scheduled, scheduled_at in the response): approving does not bring the send forward. Otherwise it is sent now and scheduled_at is null. The approval is recorded as approved only once the release works: on any failure the approval stays pending with the reason, and can be approved again once the cause is fixed (until it expires). Only one decision lands: 409 invalid_state means it was decided or expired, do not retry; 409 approval_in_progress means another decision is releasing it right now, check the list again in a moment. The key''s allowlist and daily cap are not re-checked.'
      x-required-scope: emails:send
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: 'The approval''s id: the approval_id a held POST /v1/emails returned, or an id from GET /v1/approvals.'
      - name: Idempotency-Key
        in: header
        schema:
          type: string
        description: 'Replaying the same key on the same path in this workspace within 24 hours returns the stored response, with an Idempotent-Replay: true header, instead of acting again. Only successful responses are stored, so a failed request can be fixed and retried under the same key. The body is compared (key order ignored): the same key with a different body is 422 idempotency_key_reused, so use a new key for every new request. Use an unguessable value such as a UUID.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DecideApprovalRequest'
      responses:
        '200':
          description: 'Decided: approved (released, scheduled, or skipped) or rejected'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApprovalDecision'
        '400':
          description: 'invalid_json: the request body is not valid JSON.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: 'unauthorized: no Bearer token, or the key or token is invalid, revoked or expired.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: 'plan_limit_reached: approving, and the plan''s monthly allowance cannot cover the recipients and it has no overage. The approval stays pending; upgrading, not retrying, fixes it.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: 'forbidden: the credential is an OAuth access token, the calling key made this draft, or the calling key has a guardrail (requires_approval, allowed_recipients or a daily_send_limit). Checked after the approval is found. A person in the dashboard, or a different API key without guardrails, has to decide; retrying with this credential will not help. Also forbidden: the key lacks the emails:send scope. The message names it.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: 'not_found: no approval with this id in the workspace; or approving, and its message no longer exists (the approval stays pending).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 'invalid_state: already approved or rejected, or expired; or approving, and the held message is no longer queued or failed, so it cannot be released. Do not retry. approval_in_progress: another decision is releasing it now; check again in a moment. Also idempotency_in_progress: a request with the same Idempotency-Key was still running on this path after waiting up to 8 seconds for it (a retry that finds it finished receives its response instead). Retry after a short wait.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: 'payload_too_large: the body is larger than this endpoint accepts (5 MB unless stated).'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: 'invalid_request: the body failed validation (checked before the approval is looked up; details lists each field). no_verified_identity: approving, but the sending domain the message was held on has been removed; add and verify it again, then approve. workspace_suspended: approving a message due now while sending is suspended. no_postal_address: approving marketing mail due now and the workspace has no postal address. warmup_limit: approving marketing mail due now and its sending domain has used today''s warm-up allowance. In each of these the approval stays pending. Also idempotency_key_reused: this Idempotency-Key was already used on this path with a different request body (checked right after the scope, so a credential without the scope gets 403 instead, and answered at once even while the first request is still running). Do not retry; send the new request under a new key.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: 'rate_limited: more requests than the per-key rate (600 a minute by default). Wait the seconds in the Retry-After header and retry.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: 'ses_error: approving, and the provider refused or throttled the message. A refused message is marked failed (a throttled one stays queued) and the approval stays pending, so approving again retries it.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: 'service_unavailable: the API is under heavy load and could not get a database connection in time. Usually nothing was done; a send that was already under way may have been, so check GET /v1/emails before retrying one. Wait the seconds in the Retry-After header.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
      - Approvals
      operationId: postV1ApprovalsById
      x-operation-id-source: derived
    servers:
    - url: https://api.sendraven.ai
components:
  schemas:
    ApprovalDecision:
      type: object
      description: The same keys for both decisions; a field with nothing to say is null or false.
      required:
      - id
      - status
      - message_id
      - scheduled_at
      - skipped
      - reason
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum:
          - approved
          - rejected
        message_id:
          type: string
          format: uuid
        scheduled_at:
          type:
          - string
          - 'null'
          format: date-time
          description: 'Set when approved and the draft carried a scheduled_at still in the future: the message was put on the schedule (status scheduled), not sent now. null when it was sent now, and on a rejection.'
        skipped:
          type: boolean
          description: 'True only when approved and no To address was left after re-checking suppressions and topic opt-outs: nothing was sent and the message is recorded as rejected. The approval still counts as approved. False otherwise, including on a rejection.'
        reason:
          type:
          - string
          - 'null'
          description: 'When skipped is true: suppressed:<suppression reason> (e.g. suppressed:hard_bounce) or unsubscribed_from_topic:<topic key>. null otherwise.'
    DecideApprovalRequest:
      type: object
      required:
      - decision
      - decided_by
      properties:
        decision:
          type: string
          enum:
          - approve
          - reject
        decided_by:
          type: string
          minLength: 1
          maxLength: 200
          description: Who authorised the decision, such as a reviewer's email address. Recorded as given, not verified, not returned.
        reason:
          type: string
          maxLength: 500
          description: Stored on the approval; not returned.
    Approval:
      type: object
      required:
      - id
      - message_id
      - api_key_id
      - expires_at
      - created_at
      - message
      properties:
        id:
          type: string
          format: uuid
          description: The approval id, returned as approval_id by the held send.
        message_id:
          type: string
          format: uuid
          description: The held message; queued in the email log until decided or expired. GET /v1/emails/{id} gives from and scheduled_at.
        api_key_id:
          type: string
          description: The key that made the send. That key cannot decide this approval.
        expires_at:
          type: string
          format: date-time
          description: After this it drops out of the list and cannot be decided.
        created_at:
          type: string
          format: date-time
        message:
          type:
          - object
          - 'null'
          required:
          - to
          - subject
          - text
          - html
          description: The content to review; null if the message no longer exists. No from, cc, bcc, reply_to, attachments or schedule.
          properties:
            to:
              type: array
              items:
                type: string
              description: Bare recipient addresses.
            subject:
              type: string
            text:
              type:
              - string
              - 'null'
            html:
              type:
              - string
              - 'null'
    Error:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - type
          - message
          properties:
            type:
              type: string
              description: 'Stable and safe to branch on, and the same status on every route: invalid_request (422), invalid_json (400), payload_too_large (413), unauthorized (401), forbidden (403), not_found (404), conflict (409, an identifier already taken), invalid_state (409, the resource''s current state does not allow this), plan_limit_reached (402), payment_method_required (402), billing_past_due (402), budget_exceeded (402), no_verified_identity (422), missing_variables (422), unknown_topic (422), idempotency_in_progress (409), idempotency_key_reused (422), approval_in_progress (409), rate_limited (429), daily_limit (429), recipient_not_allowed (403), invalid_schedule (422), warmup_limit (422), no_postal_address (422), workspace_suspended (422), gone (410), ses_error (502), internal_error (500), service_unavailable (503).'
            message:
              type: string
              description: For people; may change.
            details:
              type: array
              items:
                type: object
                additionalProperties: true
              description: 'On many 422 invalid_request answers: one entry per field that failed validation.'
            missing:
              type: array
              items:
                type: string
              description: 'Only on missing_variables, and always there: the names of the template variables that were not supplied.'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An API key of the form sk_live_…, created at /developers, or an OAuth access token (srv_oat_…). An OAuth token carries its grant's scopes but none of an API key's guardrails, and cannot decide approvals.
x-refined-from:
- sendraven-ai-api-openapi.json
- sendraven-ai-openapi.json