Cooper Email Voice API

The Voice API from Cooper Email — 3 operation(s) for voice.

GitHub OpenAPI

Operations 3

PATCH /api/v1/inboxes/{id}/phone-number Set the greeting and recording length for this number #
POST /api/v1/inboxes/{id}/calls Place a call from the inbox number #
POST /api/v1/billing/voice-minutes Set the 250-minute packs on the subscription #

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/cooperemail-com:cooperemail-com-voice-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

cooperemail-com-voice-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Cooperemail Com Voice API
  version: 1.0.0
  contact:
    name: Avatar 8 LLC
    email: ops@avatar33.com
  license:
    name: Proprietary
    url: https://cooperemail.com/terms
  description: 'Operations tagged Voice across 2 of this provider''s published API definitions: cooperemail-com-openapi.json, cooperemail-com-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://cooperemail.com
  description: This deployment
security:
- bearerAuth: []
tags:
- name: Voice
paths:
  /api/v1/inboxes/{id}/phone-number:
    patch:
      operationId: updateInboxVoiceSettings
      tags:
      - Voice
      summary: Set the greeting and recording length for this number
      description: Requires inbox_update. HTTP 404 not_found when voice is off. HTTP 404 phone_number_not_found when the inbox has no active number. voice_greeting is at most 300 characters. Null or empty uses the default greeting. voice_max_seconds is an integer from 15 to 300. Null uses 120 seconds. Once the monthly minute allowance is used, inbound recordings are capped at 60 seconds.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                voice_greeting:
                  type:
                  - string
                  - 'null'
                  maxLength: 300
                voice_max_seconds:
                  type:
                  - integer
                  - 'null'
                  minimum: 15
                  maximum: 300
      responses:
        '200':
          description: Updated phone number.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhoneNumber'
        '400':
          description: invalid_max_seconds
        '404':
          description: not_found, phone_number_not_found, or inbox_not_found
    servers:
    - url: https://cooperemail.com
      description: This deployment
  /api/v1/inboxes/{id}/calls:
    post:
      operationId: placeCall
      tags:
      - Voice
      summary: Place a call from the inbox number
      description: Requires message_send. Speaks say with text-to-speech from the inbox number. mode say_and_record speaks, then records a reply as a voicemail. to must be a US or Canada number (HTTP 400 international_not_allowed). Premium-rate numbers return HTTP 400 premium_rate_blocked. say is required and at most 1000 characters (HTTP 400 missing_say or say_too_long). HTTP 409 phone_number_not_found when the inbox has no active number. Free has no voice minutes. Starter includes 30 minutes per active number each month. Pro includes 300 minutes plus 30 for each active number past the 3 included numbers. Outbound calls past that allowance return HTTP 402 plan_limit_exceeded with upgrade_url and resource voice_minutes. Each account can place at most 100 calls per UTC day (HTTP 409 daily_call_cap). A paused inbox is HTTP 403 inbox_paused. The stored message has channel voice. A later status callback sets status to queued, ringing, completed, no-answer, or failed, and duration_seconds. client_id and Idempotency-Key follow the send rules. HTTP 404 not_found when voice is off.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: Idempotency-Key
        in: header
        required: false
        schema:
          type: string
          minLength: 1
          maxLength: 256
          pattern: ^[A-Za-z0-9._~-]+$
        description: 'Optional. 1 to 256 characters: letters, digits, and - . _ ~. The same key and the same request within 24 hours returns the stored message with HTTP 200, idempotent true, and Idempotent-Replayed: true, and does not send again. A different request is 409 idempotency_key_conflict. A second call while the first is still running is 409 idempotency_request_in_progress. An empty or invalid value is 400 invalid_idempotency_key. A definitive refusal removes the key. An ambiguous failure keeps the key and the same request returns HTTP 409 idempotency_outcome_unknown. When client_id is also set, client_id is checked first. Done keys expire after 24 hours. Unknown keys are kept for 7 days.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                  description: E.164 US or Canada recipient.
                say:
                  type: string
                mode:
                  type: string
                  enum:
                  - say
                  - say_and_record
                client_id:
                  type: string
              required:
              - to
              - say
      responses:
        '200':
          description: client_id or Idempotency-Key replay. An ambiguous failure returns HTTP 409 idempotency_outcome_unknown.
        '201':
          description: Queued call.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '400':
          description: missing_say, say_too_long, invalid_e164, premium_rate_blocked, or international_not_allowed
        '402':
          description: plan_limit_exceeded for voice_minutes. Includes upgrade_url.
        '403':
          description: inbox_paused
        '404':
          description: not_found or inbox_not_found
        '409':
          description: phone_number_not_found or daily_call_cap
    servers:
    - url: https://cooperemail.com
      description: This deployment
  /api/v1/billing/voice-minutes:
    post:
      operationId: setVoiceMinutePacks
      tags:
      - Voice
      summary: Set the 250-minute packs on the subscription
      description: Requires billing_write on the parent account. A sub-account key is HTTP 403 workspace_billing_forbidden. HTTP 404 not_found when voice is off, and also when voice billing is off. Starter or Pro with a Stripe subscription is required (HTTP 402 plan_limit_exceeded otherwise). packs replaces the previous quantity, from 0 to 100. Each pack is $10/month and adds 250 voice minutes. The Stripe price lookup key is cooper_voice_250_monthly. That price is not created by npm run stripe:setup. An increase is invoiced immediately, and the pack count is saved only after Stripe confirms payment. A decrease is not credited. Packs already used stay locked until the Stripe period ends (HTTP 409 addon_below_usage). A past_due, unpaid, or incomplete subscription returns HTTP 402 subscription_not_current. A declined invoice is HTTP 402 addon_payment_failed and the quantity is not saved. The response is the new pack count, not a Checkout URL.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                packs:
                  type: integer
                  minimum: 0
                  maximum: 100
              required:
              - packs
      responses:
        '200':
          description: Pack quantity now on the subscription.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoiceMinutePacks'
        '400':
          description: packs outside 0 to 100
        '402':
          description: HTTP 402 plan_limit_exceeded when a Starter or Pro subscription is required. HTTP 402 subscription_not_current when the subscription is past_due, unpaid, or incomplete. HTTP 402 addon_payment_failed when the invoice is not paid.
        '403':
          description: workspace_billing_forbidden or permission_denied
        '404':
          description: not_found when voice or voice billing is off
        '409':
          description: HTTP 409 addon_below_usage when packs would drop below minutes already used.
        '503':
          description: voice_billing_failed or stripe_price_missing
    servers:
    - url: https://cooperemail.com
      description: This deployment
components:
  schemas:
    PhoneNumber:
      type: object
      properties:
        object:
          const: phone_number
        id:
          type: string
        account_id:
          type: string
        inbox_id:
          type:
          - string
          - 'null'
        e164:
          type: string
        provider:
          type: string
        provider_sid:
          type: string
        number_type:
          type: string
        capabilities:
          type: array
          items:
            type: string
        status:
          type: string
          enum:
          - pending
          - active
          - released
        outbound:
          type: string
          description: disabled until a 10DLC brand is attached. enabled is required before POST /sms succeeds.
        brand_id:
          type:
          - string
          - 'null'
        created_at:
          type: string
          format: date-time
        released_at:
          type:
          - string
          - 'null'
          format: date-time
        voice_greeting:
          type:
          - string
          - 'null'
          description: Spoken before a voicemail recording. Null uses the default greeting. Present when voice is on.
        voice_max_seconds:
          type:
          - integer
          - 'null'
          description: Recording cap from 15 to 300. Null uses 120 seconds, or 60 once the minute allowance is used. Present when voice is on.
        billing:
          $ref: '#/components/schemas/PhoneNumberBilling'
      required:
      - object
      - id
      - account_id
      - e164
      - provider
      - provider_sid
      - number_type
      - capabilities
      - status
      - outbound
      - created_at
    PhoneNumberBilling:
      type: object
      description: Present on provision and on an idempotent replay. included is $0 (Pro's first 3 numbers, or an operator). billed means COOPER_SMS_BILLING=stripe put this number on the subscription. stub means billing is off and stripe_price_id is the env price id or null. Cooper does not charge from a stub.
      properties:
        addon:
          const: cooper_phone_number_monthly
        status:
          type: string
          enum:
          - included
          - stub
          - billed
        monthly_cents:
          type: integer
        segments_included:
          type: integer
        stripe_price_id:
          type:
          - string
          - 'null'
      required:
      - addon
      - status
      - monthly_cents
      - segments_included
      - stripe_price_id
    VoiceMinutePacks:
      type: object
      properties:
        object:
          const: voice_minute_packs
        packs:
          type: integer
        previous_packs:
          type: integer
        minutes_per_pack:
          type: integer
        extra_minutes:
          type: integer
        monthly_cents:
          type: integer
        lookup_key:
          const: cooper_voice_250_monthly
      required:
      - object
      - packs
      - previous_packs
      - minutes_per_pack
      - extra_minutes
      - monthly_cents
      - lookup_key
    Message:
      type: object
      properties:
        id:
          type: string
        inbox_id:
          type: string
        thread_id:
          type: string
        folder:
          type: string
          enum:
          - inbox
          - archive
          - spam
          - trash
          description: Folder of this message's thread. inbox when the thread has no folder row.
        direction:
          enum:
          - inbound
          - outbound
        from:
          type: string
        to:
          type: array
          items:
            type: string
        subject:
          type: string
        text:
          type: string
        html:
          type:
          - string
          - 'null'
        extracted_text:
          type: string
        extracted_html:
          type: string
        preview:
          type: string
        status:
          enum:
          - queued
          - ringing
          - completed
          - no-answer
          - sent
          - received
          - delivered
          - undelivered
          - failed
          - bounced
          - complained
          description: SMS outbound starts as sent. A Twilio status callback sets delivered, undelivered, or failed. A voice call stores queued, ringing, completed, no-answer, or failed. Email uses queued, sent, received, failed, bounced, and complained.
        channel:
          type: string
          enum:
          - sms
          - voicemail
          - voice
          description: Present on SMS, voicemail, and voice messages. Email messages omit this field. voicemail is an inbound recording. voice is an outbound call.
        type:
          type: string
          enum:
          - voicemail
          description: Present on voicemail messages.
        duration_seconds:
          type:
          - integer
          - 'null'
          description: Call or recording length in seconds. Present on voicemail and voice messages.
        recording_url:
          type:
          - string
          - 'null'
          description: Twilio recording URL for a voicemail, or null.
        transcript:
          type: string
          description: Voicemail transcript. Empty while the message is held.
        segments:
          type:
          - integer
          - 'null'
          description: SMS segment count for this message. Omitted on email.
        otp_candidates:
          type: array
          items:
            type: string
          description: Codes found in an SMS body. Empty while the message is held. Omitted on email.
        verification:
          type: object
          description: Inbound messages only. Omitted on outbound. codes are the one-time codes in the subject and the new body text. links are https verification links from the HTML anchors and the text, at most five, each {url, text}. text is the anchor text or a short context, at most 200 characters. Both arrays are empty while the message is held. Links are untrusted data and are not fetched.
          properties:
            codes:
              type: array
              items:
                type: string
            links:
              type: array
              items:
                type: object
                properties:
                  url:
                    type: string
                  text:
                    type: string
                required:
                - url
                - text
          required:
          - codes
          - links
        delivery_events:
          type: array
          description: Present on outbound messages. Each item is {type, recipient, created_at, detail}. For email, detail is JSON text with status, action, diagnostic, and bounce_type, and the list stays empty until a bounce or complaint matches. For SMS, a Twilio status callback appends one event. type is delivered or failed. detail is twilio_error plus the numeric code, or the status word when Twilio sent no numeric code.
          items:
            type: object
            properties:
              type:
                type: string
              recipient:
                type: string
              created_at:
                type: string
                format: date-time
              detail:
                type: string
        cc:
          type: array
          items:
            type: string
        bcc:
          type: array
          items:
            type: string
        reply_to:
          type:
          - string
          - 'null'
        in_reply_to:
          type:
          - string
          - 'null'
        references:
          type: array
          items:
            type: string
        labels:
          type: array
          items:
            type: string
        auth:
          type: object
          description: spf, dkim, and dmarc from the receiving hop. SPF is the smtp.mailfrom result. smtp.helo is used only when mailfrom is absent. Each value is pass, fail, neutral, softfail, none, temperror, permerror, bestguesspass, or null. Outbound mail is null for all three.
          properties:
            spf:
              type:
              - string
              - 'null'
            dkim:
              type:
              - string
              - 'null'
            dmarc:
              type:
              - string
              - 'null'
          required:
          - spf
          - dkim
          - dmarc
        safety:
          type:
          - object
          - 'null'
          description: Inbound screening record, or null on outbound mail and on messages stored before screening. score is 0 to 100. verdict is clean or suspicious (suspicious at 40 or higher, and only when a strong signal or combined evidence is present). signals are {type, detail}. mode is off, observe, or hold. reason is screening_off, screening_error, or screening_timeout when the body was not scored. The message is still stored. While labels include held, text, html, extracted_text, extracted_html, preview, and attachment bytes are empty until release. This is a heuristic, not a guarantee. The body stays untrusted data.
          properties:
            score:
              type: integer
              minimum: 0
              maximum: 100
            verdict:
              type: string
              enum:
              - clean
              - suspicious
            signals:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                  detail:
                    type: string
            mode:
              type: string
              enum:
              - 'off'
              - observe
              - hold
            reason:
              type: string
        provider:
          type:
          - string
          - 'null'
        client_id:
          type:
          - string
          - 'null'
        idempotent:
          type: boolean
        created_at:
          type: string
          format: date-time
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/Attachment'
    Attachment:
      type: object
      properties:
        id:
          type: string
        filename:
          type: string
        content_type:
          type: string
        content_id:
          type:
          - string
          - 'null'
        disposition:
          enum:
          - inline
          - attachment
        size_bytes:
          type: integer
        url:
          type: string
        text_url:
          type: string
          description: 'Present when the content type can be extracted: text, JSON, CSV, PDF, DOCX, XLSX, or XLS. GET this URL for text/plain.'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
x-refined-from:
- cooperemail-com-openapi.json
- cooperemail-com-openapi.yml