VoixCall

VoixCall for developers

Quickstart

Three ways in, each under five minutes: Claude Code, a claude.ai or ChatGPT connector, or plain curl against the REST API.

A. Connect Claude Code

Claude Code speaks MCP over HTTP and handles OAuth itself, including registration by its own client metadata document.

Terminal
claude mcp add --transport http voixcall https://api.voixcall.com/mcp
claude mcp login voixcall
  1. The second command opens app.voixcall.com in your browser. Sign in if you need to.
  2. The consent page names the client (Claude Code), the permissions it asked for, and the host it will redirect to. Choose Allow.
  3. Back in Claude Code, ask: which VoixCall account am I connected to? It calls voixcall_whoami and answers with the account's name and email.

To disconnect later, either run claude mcp remove voixcall or open Settings โ†’ Connected apps in the web app and choose Disconnect; the second one revokes the tokens on our side as well.

B. Connect claude.ai or ChatGPT

In claude.ai, add a custom connector with the URL https://api.voixcall.com/mcp. Leave the client id and secret fields empty: the connector discovers the authorization server from the URL, registers itself and runs the OAuth flow. You approve once on app.voixcall.com, then the VoixCall tools appear in the chat. Hosted connectors use the same standard MCP discovery and OAuth 2.1 flow. Unlike Claude Code (which is verified against production), they connect from the vendor's servers with an https callback, which we have not yet exercised end to end.

ChatGPT's connector settings take the same server URL and use the same standard MCP discovery and OAuth 2.1 flow; like claude.ai, it connects from the vendor's servers with an https callback, which we have not yet exercised end to end. If you try it, tell us at support@voixcall.com.

Any other MCP client that supports Streamable HTTP and OAuth works the same way. Details and the tool list are on the MCP page.

C. Call the REST API with curl

The API accepts OAuth 2.1 access tokens (and, once the Settings screen for them ships, personal API keys). Getting a token by hand is the standard authorization-code flow with PKCE; the steps below do it with curl and a browser and take about two minutes. Nothing here needs a client secret: every client is a public client.

1. Read the server metadata

All endpoints, supported scopes and PKCE methods come from the authorization-server metadata document (RFC 8414). Nothing in this guide is hard-coded that the document does not also say.

Terminal
curl -s https://api.voixcall.com/.well-known/oauth-authorization-server

2. Register a client

If you host a public client metadata document (an https URL that returns your client's metadata, with client_id equal to that URL), skip this step and use the URL as your client_id. Otherwise register once with Dynamic Client Registration. Loopback redirect URIs (http://127.0.0.1, http://localhost, http://[::1], any port) are allowed for native and script clients.

Terminal
curl -s https://api.voixcall.com/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My VoixCall script",
    "redirect_uris": ["http://127.0.0.1:8765/callback"],
    "application_type": "native",
    "token_endpoint_auth_method": "none",
    "grant_types": ["authorization_code", "refresh_token"],
    "response_types": ["code"]
  }'
Response (201 Created)
{
  "client_id": "dcr_โ€ฆ",
  "client_id_issued_at": 1790612000,
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "client_name": "My VoixCall script",
  "application_type": "native"
}

Keep the client_id. Registrations that are never used are purged after 30 days.

3. Send the user to the authorization page

Build a PKCE verifier and challenge, then open the authorization URL. Ask only for the scopes you need: the example requests rates:read alone, which is enough for /v1/me. Assistants are asked to start with the read-only set rates:read credits:read calls:read contacts:read and request more later. resource is required and must be exactly https://api.voixcall.com/v1 (or โ€ฆ/mcp for an MCP client); the token is bound to it.

Terminal (macOS: open; Linux: xdg-open)
CLIENT_ID="dcr_โ€ฆ"                       # from the registration response
CODE_VERIFIER=$(openssl rand -base64 48 | tr -d '=+/')
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')
STATE=$(openssl rand -hex 16)

open "https://api.voixcall.com/oauth/authorize?response_type=code\
&client_id=$CLIENT_ID\
&redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Fcallback\
&scope=rates%3Aread\
&state=$STATE\
&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256\
&resource=https%3A%2F%2Fapi.voixcall.com%2Fv1"

Sign in and choose Allow. The browser is redirected to http://127.0.0.1:8765/callback?code=โ€ฆ&state=โ€ฆ&iss=https://api.voixcall.com. Nothing is listening there, so the page shows a connection error: that is expected. Copy the code value from the address bar. It is single-use and expires 60 seconds after it was issued, so do step 4 right away.

4. Exchange the code for tokens

Terminal
CODE="โ€ฆ"                                # the code= value from the redirect URL

curl -s https://api.voixcall.com/oauth/token \
  -d grant_type=authorization_code \
  -d code="$CODE" \
  -d code_verifier="$CODE_VERIFIER" \
  -d client_id="$CLIENT_ID" \
  -d redirect_uri=http://127.0.0.1:8765/callback \
  -d resource=https://api.voixcall.com/v1
Response (200 OK)
{
  "access_token": "vcat_โ€ฆ",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "vcrt_โ€ฆ",
  "scope": "rates:read"
}

Access tokens (vcat_) last one hour. Refresh tokens (vcrt_) last 30 days, or 14 days without use, and are rotated on every refresh: the old one stops working and presenting it again revokes the whole grant.

5. Call /v1/me

Terminal
TOKEN="vcat_โ€ฆ"

curl -s https://api.voixcall.com/v1/me \
  -H "Authorization: Bearer $TOKEN"
Response (200 OK)
{
  "object": "user",
  "id": "usr_0f8c2b6a4d1e4c7b9a3e5d2f1c0b9a87",
  "email": "you@example.com",
  "display_name": "Your Name",
  "country_code": null,
  "time_zone": null,
  "livemode": true
}

id is the account id with the usr_ prefix. country_code and time_zone are always null today (not stored yet). livemode is true for OAuth tokens and live API keys. /v1/me works with any scope. This is the only /v1 operation live today; the reference grows as endpoints ship.

6. Refresh

client_id is required on refresh (public client). A scope parameter may narrow the token's scopes, never widen them.

Terminal
curl -s https://api.voixcall.com/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token="vcrt_โ€ฆ" \
  -d client_id="$CLIENT_ID"

API keys

Personal API keys are sent the same way, as a bearer token: Authorization: Bearer vc_live_โ€ฆ. Keys work on /v1 only and are rejected at /mcp; test keys (vc_test_) additionally see only test-mode data. Keys carry a name, a subset of scopes, an expiry (90 days by default, one year at most) and an optional IP allowlist.

coming The management endpoints exist, but the screen to create a key in Settings has not shipped yet, so there is no self-serve way to obtain one today. Use OAuth until it does; the changelog will say when.

Terminal
curl -s https://api.voixcall.com/v1/me \
  -H "Authorization: Bearer vc_live_โ€ฆ"

What a failure looks like

Every error is the same JSON envelope. Every response carries Request-Id; /v1 responses carry VoixCall-Version; rate-limited responses carry the RateLimit headers.

Terminal
curl -s https://api.voixcall.com/v1/me
# HTTP 401, WWW-Authenticate: Bearer error="invalid_token", resource_metadata="https://api.voixcall.com/.well-known/oauth-protected-resource/v1"
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_token",
    "message": "Provide a bearer access token.",
    "param": null,
    "doc_url": "https://voixcall.com/developers/errors#invalid_token",
    "request_id": "req_Fa3rR6ZW8v3AM31xlv9CYQ"
  }
}

The error catalogue lists every code with its status and what to do; rate limits explains the headers. Quote the request_id when you write to support@voixcall.com.