VOYGR Core API
The core API from VOYGR — 2 operation(s) for core.
The core API from VOYGR — 2 operation(s) for core.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
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.curl "https://apis.io/api/v1/apis/voygr-core-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
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