Skip to main content

REST API

The endpoints a developer key can use, with request and response examples, error formats and limits.

What you will achieve

You will read and change your workspace from code, and place an outbound call.

Base URL and authentication

Base URL: https://phynxa.com/api. All bodies are JSON. Authenticate with Authorization: Bearer nxa_live_... (see API keys).

Note. Examples below use values made up for illustration. Replace the key and ids with your own.

Endpoints a key can use

AreaEndpoints
AgentsGET /agents, POST /agents, GET /agents/{id}, PATCH /agents/{id}, DELETE /agents/{id}, GET and PUT /agents/{id}/tools, GET and PUT /agents/{id}/knowledge
CallsGET /calls, GET /calls/{id}, GET /calls/{id}/transcript, POST /calls/{id}/review, POST /calls/outbound
ContactsGET /contacts, POST /contacts, POST /contacts/import, PATCH /contacts/{id}, DELETE /contacts/{id}, POST /contacts/{id}/call, POST /contacts/{id}/schedule
Scheduled callsGET /scheduled-calls, DELETE /scheduled-calls/{id}
CampaignsGET /campaigns, POST /campaigns, GET /campaigns/{id}, POST /campaigns/{id}/start, POST /campaigns/{id}/cancel, DELETE /campaigns/{id}
ToolsGET /tools, POST /tools, GET, PATCH and DELETE /tools/{id}, POST /tools/{id}/test
KnowledgeGET and POST /knowledge, GET, PATCH and DELETE /knowledge/{id}, documents, POST /knowledge/{id}/search
WebhooksGET and POST /webhooks, GET, PATCH and DELETE /webhooks/{id}, PUT /webhooks/{id}/agents, GET /webhooks/{id}/deliveries, POST /webhooks/{id}/test
Forms and captures/forms, /captures
ReportsGET /stats, GET /insights

List agents

bash
curl https://phynxa.com/api/agents -H "Authorization: Bearer nxa_live_YOUR_KEY"

Returns a JSON array. One element (shortened):

json
{
  "id": "c2997c6f-9d1c-41bb-9ba7-f2e3c6e2a648",
  "name": "Reception Marina",
  "description": "",
  "language": "en",
  "model": "openai:gpt-4o-mini",
  "stt_provider": "deepgram-nova-3",
  "tts_provider": "cartesia",
  "voice": "a0e99841-438c-4a64-b679-ae501e7d6091",
  "greeting": "Hello! How can I help you today?",
  "temperature": 0.6,
  "can_end_call": true,
  "can_transfer_call": false,
  "transfer_number": "",
  "call_direction": "inbound",
  "phone_number": "",
  "active": true,
  "webhook_id": "",
  "timezone": "UTC",
  "created_at": "2026-10-10T23:27:33.841629+00:00",
  "updated_at": "2026-10-10T23:27:33.841629+00:00"
}

active is true for a published agent. A few flags such as capture_enabled come back as 0 or 1.

Create and change an agent

bash
curl -X POST https://phynxa.com/api/agents \
  -H "Authorization: Bearer nxa_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "API example agent", "language": "en"}'

Creating takes name (required), and optionally language (en, ur, hi, ar, fr, es, zh), timezone, template_id, business_name and template_inputs. The reply is the new agent. On the Free plan the new agent has active: false.

Change fields with PATCH. Only what you send changes, and unknown fields are rejected so a typo cannot pass silently:

bash
curl -X PATCH https://phynxa.com/api/agents/AGENT_ID \
  -H "Authorization: Bearer nxa_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"greeting": "Thanks for calling Acme. How can I help?", "temperature": 0.4}'

Fields you can change include name, description, model (as provider:model, for example openai:gpt-4.1), system_prompt, greeting, stt_provider, tts_provider, voice, language, temperature, max_turn_seconds, idle_prompts, idle_message, can_end_call, can_transfer_call, transfer_number, phone_number, call_direction, webhook_id, capture_form_id, capture_enabled, call_summary_enabled, timezone, business_name, business_address, business_hours and active (publish or unpublish). timezone is the agent's clock only; business_address is what the agent gives as its location. DELETE /agents/{id} answers 204.

Place an outbound call

bash
curl -X POST https://phynxa.com/api/calls/outbound \
  -H "Authorization: Bearer nxa_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "AGENT_ID", "to_number": "+14155552671"}'

On success you receive 202:

json
{ "call_sid": "CA0123456789abcdef0123456789abcdef", "to": "+14155552671" }

The agent must be published and set to Outbound or Inbound / Outbound, and your workspace needs Twilio connected. Errors:

Statusdetail
404Agent not found
409This agent is paused, or That number belongs to a blocked contact.
422This agent is inbound-only and cannot place calls., or Twilio's own message
429Call limit reached. Try again later.

Read calls and transcripts

GET /calls returns finished calls, newest first, up to 200. Each has id, agent_id, agent_name, started_at, ended_at, seconds, turns, direction, from_number, to_number, outcome, cost_usd and the review fields summary, intent, sentiment, outcome_label, score, action_items and entities, plus the cost breakdown (llm_cost_usd, stt_cost_usd, tts_cost_usd and so on).

GET /calls/{id} returns one call with its transcript and tool_calls. GET /calls/{id}/transcript returns just the lines, each with role (user or assistant), text and at.

GET /stats returns totals:

json
{
  "agents": 4,
  "active_agents": 3,
  "calls": 29,
  "minutes": 64.28,
  "avg_call_seconds": 133.0,
  "total_cost": 1.59,
  "avg_cost_per_call": 0.0548,
  "p95_latency_ms": 0.0
}

Contacts

bash
curl -X POST https://phynxa.com/api/contacts \
  -H "Authorization: Bearer nxa_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Sara K.", "phone_number": "+971501234567", "country_code": "AE", "timezone": "Asia/Dubai", "status": "lead"}'

status is lead, customer, engaged or blocked. POST /contacts/import takes {"contacts": [ ... ]} of up to 5,000 rows with name, phone_number, country_code and timezone.

Webhooks

POST /webhooks with {"name": "CRM sync"} creates one; set its details with PATCH /webhooks/{id}, which accepts url, method, headers, secret, events, payload_fields, active, timeout_secs (up to 60) and retries (1 to 5):

bash
curl -X PATCH https://phynxa.com/api/webhooks/WEBHOOK_ID \
  -H "Authorization: Bearer nxa_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://yoursite.com/hooks/calls", "secret": "whsec_your_secret", "payload_fields": ["call", "review", "transcript"]}'

POST /webhooks/{id}/test sends a sample and returns {"ok": true, "status_code": 200, "error": "", "duration_ms": 2}. The secret is never returned: responses show secret_configured.

Errors

Errors are JSON with a detail.

StatusMeaningExample
401No or invalid key, or a path a key may not use{"detail": "Sign in to continue."}
403Not allowed for this role
404Not found, or not in your workspace{"detail": "Agent not found"}
409Conflict{"detail": "This agent is paused"}
413Request body over 25 MB
422Invalid inputA message string, or a list of problems (below)
429Rate limit{"detail": "Rate limit reached for this key."}

A validation error lists each problem:

json
{
  "detail": [
    {
      "type": "string_too_short",
      "loc": ["body", "name"],
      "msg": "String should have at least 1 character",
      "input": "",
      "ctx": { "min_length": 1 }
    }
  ]
}

Rate limits

LimitValue
Requests per key600 per minute
Outbound calls20 per person and 200 per workspace per hour
Webhook and tool test calls30 per minute
Knowledge upload and text30 per minute; web crawls 5 per minute; searches 60 per minute

Testing

Run the list-agents example. Then create an agent and delete it again.

Expected result

JSON responses as shown, and 204 on deleting.

Troubleshooting

  • 401 on every request. Check the Bearer prefix and that the key was not revoked.
  • 422 "Extra inputs are not permitted". A field name is misspelled.
  • 429. Slow down and retry after a pause.

Something here does not match what you see in the dashboard? Let us know.