VOYGR Core API

The core API from VOYGR — 2 operation(s) for core.

Operations 2

GET /health Health check #
GET /v1/usage Get API usage statistics #

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/voygr-core-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 email required.

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

OpenAPI Specification

voygr-core-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Voygr Calls Core API
  description: "\nProgrammatic outbound phone calls executed by an AI voice agent. Submit a task,\nthe agent places the call, conducts the conversation, and returns a structured\noutcome with a full transcript.\n\n## Authentication\n\nEvery request needs the `X-API-Key` header. Keys are issued per customer and\ncarry a credit quota, rate limits, and a concurrent-call limit.\n\n## Placing a call\n\n`POST /calls` accepts two request shapes — pick one per call.\n\n**Freeform** — describe the task in plain language:\n\n```bash\ncurl -s https://api.voygr.tech/calls   -H \"X-API-Key: $API_KEY\" -H \"Content-Type: application/json\"   -d '{\"target_phone\": \"+15551234567\",\n       \"brief\": \"Ask what time the kitchen closes tonight.\",\n       \"language\": \"en\"}'\n```\n\n**Structured** — a machine-readable `intent` plus `slots`, validated\ndeterministically before anything is dialed. Five intents are supported:\n\n| Intent | Required slots |\n|---|---|\n| `inquiry` | `target_phone`, `question` |\n| `info_gathering` | `target_phone`, `questions` |\n| `issue_resolution` | `target_phone`, `issue_description` |\n| `booking` | `target_phone`, `name`, `date`, `time`, `party_size` |\n| `cancellation` | `booking_id` — no phone; it comes from the stored booking |\n\nAn incomplete submission returns `422` listing exactly what is missing, each\nslot with a `suggested_question` to relay to your user — submit, collect,\nresubmit. Validation never dials and never charges. (The credit-hold check\nruns first, so a key that cannot cover the hold gets `402` even for an\nincomplete submission.)\n\n`language` accepts `en`, `es`, `fr`, `de`, `hi`, `ru`, `pt`, `ja`, `it`,\n`nl`, `sr`, `tr`, `pl`, or `auto` (the default); any other code is refused\nwith `422 unsupported_language`.\n\nThe success envelope differs by shape: freeform wraps the call object in\n`{\"call\": {...}}`; structured returns a flat envelope with top-level\n`call_id`, `status_url`, and `answer_url`. Both are documented with examples\non the operation below.\n\n## Call lifecycle\n\nCalls are asynchronous. Poll `GET /calls/{call_id}` until `status` reaches\n`completed`, `failed`, or `cancelled` — typically 30-90 seconds. The terminal\nresponse carries `outcome_type`, `outcome_summary`, and `transcript_full`.\nThere is no completion webhook.\n\nFor live progress, poll `GET /calls/{call_id}/events?after_event_id=N` with\nshort requests, advancing the cursor to the last `id:` you received — the\nbody is SSE-formatted text, but do NOT hold a long-lived stream open, and use\nthe query cursor (the gateway strips the `Last-Event-ID` header). If the\nagent needs input mid-call it emits an `ask_user` event — create the call\nwith `ask_user_mode: \"stream\"` to receive these, and respond via\n`POST /calls/{call_id}/answer`. A queued or ringing call can be aborted with\n`POST /calls/{call_id}/cancel`.\n\nOnce the call ends, `GET /calls/{call_id}/transcript-merged` returns the\ncomplete two-sided transcript rebuilt from the dual-channel recording —\nincluding speech the live pipeline never transcribed (IVR phone trees, hold\nannouncements). The live `transcript_full` stays real-time-only; the merged\none is the complete record. A `202 {\"status\": \"merger_pending\"}` means the\nmerge (which fires seconds after the call ends) hasn't finished — retry\nafter the `transcript_ready` SSE event, or force it with\n`POST /calls/{call_id}/transcript-merged/rebuild`.\n\n## Billing\n\nThe hold and the charge are different numbers:\n\n| Event | Credits |\n|---|---|\n| Hold at dial time (`credits_reserved`) | 30 — frozen, refundable, NOT a charge |\n| Successful outcome (`success_*`) — `credits_charge_on_success` | 10 |\n| Unsuccessful outcome (`failed_*` — no answer, voicemail, technical) | 0 |\n\nThe hold is released at completion and you are only ever charged the settled\namount. Requests are rejected with `402` when the available balance cannot\ncover the hold.\n\n`GET /v1/usage` reports `available` (spendable right now) and\n`call_credit_hold` (what one call freezes), so `available // call_credit_hold`\nis how many calls you can start.\n\n## Limits\n\n- Free keys: 5 requests/second, 10 requests/minute. Paid keys: 10\n  requests/second, 100 requests/minute (`429` beyond).\n- Concurrent calls per key are limited (`409` with `active_call_ids` at the\n  cap; typically 2).\n- Service maintenance windows return `503` with a `resume_at` timestamp.\n\n## Acceptable use\n\nCalls are transactional and user-initiated only: no telemarketing,\nsolicitation, bulk dialing, or harassment. The agent discloses that it is an\nAI assistant and that the call is recorded; disclosure is not configurable.\nUnited States destinations only. Recordings and transcripts are retained for\na maximum of 90 days.\n\n\nCredit rates: validation, enrichment, business status and categorize are 1 credit per request. An AI booking call is 10 credits. Credits never expire."
  version: 1.0.0
servers:
- url: https://api.voygr.tech
  description: Production (stated by the provider in the spec description curl examples, api.voygr.tech/docs, and callwright-skill SKILL.md)
tags:
- name: core
paths:
  /health:
    get:
      tags:
      - core
      summary: Health check
      description: Check if the API server is running
      operationId: health_check_health_get
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
  /v1/usage:
    get:
      tags:
      - core
      summary: Get API usage statistics
      description: Get current usage, quota, and reset date for the API key.
      operationId: get_usage_v1_usage_get
      parameters:
      - name: X-API-Key
        in: header
        required: false
        schema:
          anyOf:
          - type: string
          - type: 'null'
          title: X-Api-Key
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageResponse'
        '401':
          description: Missing API key header
          content:
            application/json:
              example:
                success: false
                error: API key required. Include X-API-Key header.
                error_code: AUTHENTICATION_ERROR
                request_id: ad33009a-fdfe-4e25-9650-4a49099c3d4a
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Invalid, revoked, or unauthorized API key
          content:
            application/json:
              example:
                success: false
                error: Invalid or revoked API key
                error_code: AUTHENTICATION_ERROR
                request_id: 25b104f0-9ad0-4fc7-8530-c5d5ff8d9698
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ErrorResponse:
      properties:
        success:
          type: boolean
          title: Success
          description: Always false for errors
          default: false
        error:
          type: string
          title: Error
          description: Error message
        error_code:
          anyOf:
          - type: string
          - type: 'null'
          title: Error Code
          description: Error category code (VALIDATION_ERROR, MODEL_ERROR, EXTERNAL_API_ERROR, etc.)
        request_id:
          anyOf:
          - type: string
          - type: 'null'
          title: Request Id
          description: Request ID for tracing
        validation_timestamp:
          anyOf:
          - type: string
          - type: 'null'
          title: Validation Timestamp
          description: UTC timestamp when error response was produced (ISO 8601).
        detail:
          anyOf:
          - additionalProperties: true
            type: object
          - type: 'null'
          title: Detail
          description: Additional error details
      type: object
      required:
      - error
      title: ErrorResponse
      description: Error response model.
      examples:
      - success: false
        error: API key required. Include X-API-Key header.
        error_code: AUTHENTICATION_ERROR
        request_id: ad33009a-fdfe-4e25-9650-4a49099c3d4a
      - success: false
        error: Invalid or revoked API key
        error_code: AUTHENTICATION_ERROR
        request_id: 25b104f0-9ad0-4fc7-8530-c5d5ff8d9698
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
            - type: string
            - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
      - loc
      - msg
      - type
      title: ValidationError
    UsageResponse:
      properties:
        tier:
          type: string
          title: Tier
          description: API key tier (free, paid, enterprise)
        api_key_id:
          type: string
          title: Api Key Id
          description: API key ID
        customer_name:
          type: string
          title: Customer Name
          description: Customer name
        quota_limit:
          type: integer
          title: Quota Limit
          description: Maximum requests allowed per period
        current_usage:
          type: integer
          title: Current Usage
          description: Current usage count
        remaining:
          type: integer
          title: Remaining
          description: Remaining requests
        available:
          anyOf:
          - type: integer
          - type: 'null'
          title: Available
          description: Credits spendable right now — same value as `remaining`, named for the question callers ask. Already net of credits frozen by in-flight reservations.
        call_credit_hold:
          anyOf:
          - type: integer
          - type: 'null'
          title: Call Credit Hold
          description: Credits ONE outbound call freezes at dial time (a refundable hold, not a charge). available // call_credit_hold is the CREDIT-limited bound on calls in flight — entitlement and the per-customer concurrency cap gate independently, so it is not a guarantee that many will start.
        percentage_used:
          type: number
          title: Percentage Used
          description: Percentage of quota used
        reset_date:
          type: string
          title: Reset Date
          description: Date when usage resets (YYYY-MM-DD)
        period:
          type: string
          title: Period
          description: Quota period (monthly, weekly, daily)
        status:
          type: string
          title: Status
          description: API key status (active, revoked, suspended)
        validation_timestamp:
          anyOf:
          - type: string
          - type: 'null'
          title: Validation Timestamp
          description: UTC timestamp when usage response was produced (ISO 8601).
      type: object
      required:
      - tier
      - api_key_id
      - customer_name
      - quota_limit
      - current_usage
      - remaining
      - percentage_used
      - reset_date
      - period
      - status
      title: UsageResponse
      description: Response model for usage endpoint.
      examples:
      - api_key_id: f4d0a2c2-f73f-4de6-ac3e-f42ce35af4d6
        customer_name: Acme Inc
        quota_limit: 10000
        current_usage: 2375
        remaining: 7625
        percentage_used: 23.75
        reset_date: '2026-03-31'
        period: monthly
        status: active
      - api_key_id: eaa59659-7fab-4d1f-a80d-4f1e0f9388e4
        customer_name: Beta Foods
        quota_limit: 5000
        current_usage: 5000
        remaining: 0
        percentage_used: 100.0
        reset_date: '2026-03-01'
        period: monthly
        status: active