REST · WebSocket · gRPC

API
reference.

312 endpoints, complete OpenAPI spec, idempotency on every mutation, and a public uptime contract. No black boxes.

Base URL
api.rozper.com
Version
v2026.05
Rate limit
1000 rps
POST/v2/calls
"color:#22D3EE">curl "color:#22D3EE">-X "color:#34D399;font-weight:600">POST https://api.rozper.com/v2/calls \
  "color:#22D3EE">-H "Authorization: Bearer $ROZPER_API_KEY" \
  "color:#22D3EE">-H "Content-Type: application/json" \
  "color:#22D3EE">-d '{
    "to":   "+14155551234",
    "from": "+12025550100",
    "url":  "https://your.app/voice/answer"
  }'
201Response · 84 ms
{
  "id": "call_01HXY7ZQ9V3J3X8K5N",
  "status": "queued",
  "to":     "+14155551234",
  "from":   "+12025550100",
  "created_at": "2026-05-12T14:23:01Z"
}
§01 · Authentication

Bearer tokens.
Scoped. Rotatable.

Every request carries a project key as a Bearer token. Keys are scoped (read, write, billing), rotatable without downtime, and can be IP-pinned from the dashboard.

  • Per-environment keys (test / live)
  • OAuth 2.0 client credentials supported
  • Mutual TLS available on Enterprise
Authorization header
cURLNodePythonGo
# .env  →  never commit me
ROZPER_API_KEY=sk_live_8FzqQ...XW7p

# request
curl https://api.rozper.com/v2/account \
  -H "Authorization: Bearer $ROZPER_API_KEY"

# 200 OK
{
  "id": "acct_01HXY7ZQ9V3J3X8K5N",
  "scopes": ["calls.write", "messages.write", "numbers.read"],
  "rate_limit": { "limit": 1000, "remaining": 998, "reset": 1715520000 }
}
§02 · Reference

Explore every endpoint.

callsCreate a call

Create a call

Originate an outbound PSTN call. Returns immediately with a queued call object — listen on webhooks for state changes.

POST/v2/calls
Parameters
tostringrequired

E.164 destination number.

fromstringrequired

Verified or rented Rozper number.

urlstring

HTTPS endpoint that returns voice instructions when the call connects.

recordboolean

Record both legs to your storage. Default false.

timeoutinteger

Ring timeout in seconds. Default 60.

Request · node● live
const call = await rozper.calls.create({
  to:   "+14155551234",
  from: "+12025550100",
  url:  "https://your.app/voice/answer",
})
Response · 201 created84 ms
{
  "id": "call_01HXY7ZQ9V3J3X8K5N",
  "object": "call",
  "created_at": "2026-05-12T14:23:01Z"
}
§03 · Errors

Predictable, machine-readable errors.

Every 4xx and 5xx returns the same shape: a stable code, a human-readable message, and a request id you can paste to support.

Error envelope
{
  "error": {
    "code": "invalid_param",
    "message": "to: must be E.164",
    "request_id": "req_01HXY7…",
    "param_errors": [
      { "param": "to", "reason": "format" }
    ]
  }
}
400
bad_request

Malformed request body or missing required field.

401
unauthorized

Missing, expired, or revoked API key.

403
forbidden

Key lacks the scope required for this resource.

404
not_found

The resource id does not exist for this account.

409
conflict

Idempotency key collides with a different payload.

422
invalid_param

A parameter failed validation. Inspect param_errors[].

429
rate_limited

Backoff using the Retry-After header.

500
server_error

We were notified. Retry idempotent calls.

§04 · Webhooks

Signed, retried, replay-protected.

Every event is delivered with an HMAC signature, a unique event id, and a UTC timestamp. We retry with exponential backoff for up to 24 hours.

HMAC-SHA256 signature in Rozper-Signature
Up to 8 retries · 24h window
Send to multiple endpoints simultaneously
Verify a webhook · Node✓ constant-time compare
import { verify } from "@rozper/sdk/webhooks"

app.post("/webhooks/rozper", (req, res) => {
  const ok = verify({
    payload:   req.rawBody,
    signature: req.header("Rozper-Signature"),
    secret:    process.env.ROZPER_WEBHOOK_SECRET,
  })
  if (!ok) return res.status(401).end()

  const event = JSON.parse(req.rawBody)
  switch (event.type) {
    case "call.completed": /* … */
    case "recording.ready": /* … */
  }
  res.json({ received: true })
})
Event catalog · 32 total
call.initiated

Outbound call accepted by the carrier.

call.ringing

Far-end is ringing.

call.answered

Far-end answered (or AMD detected human).

call.completed

Call ended. Includes duration, billing, leg metadata.

recording.ready

Recording asset uploaded and signed URL available.

message.delivered

Carrier delivery receipt (where supported).

agent.handoff

AI agent escalated to a human queue.

number.purchased

Number acquisition completed.

§05 · Changelog

Every change, in plain English.

  1. 2026-05-10
    v2026.05
    • featVoice agents now support tool calling with streaming responses.
    • featNew /v2/numbers/port endpoint for programmatic LNP submissions.
  2. 2026-04-22
    v2026.04
    • fixIdempotency cache now correctly honors 24h TTL on POST /calls.
    • choreDeprecated v1 endpoints removed (announced 2025-11).
  3. 2026-03-31
    v2026.03
    • featWebSocket media-streams beta is now generally available.
    • featWhatsApp template messages added under /v2/messages.