Skip to content

API Keys ​

Your backend needs to talk to Perfox — create an agent, upload a document to the Knowledge Base, read a transcript, send a WhatsApp message. API keys authenticate those server-to-server calls, and each key's scopes decide exactly what it is allowed to do.

Try the Platform API live

Browse and call every endpoint on this page — authenticated with your own key — in the API Explorer. The same operations are available to any MCP-capable agent in the MCP Explorer.

Creating a key ​

Open Developer in the Studio sidebar (under Admin) and stay on the API keys tab. Click + New key, give it a name, and tick the scopes it needs. (See the Developer Hub Guide for the rest of that page.)

A key looks like this:

sk_<64 hexadecimal characters>

The full key is shown in a dialog once, right after you create it. Copy it into your secret manager then. In the key list you only ever see the sk_ prefix and the first eight characters, which is enough to tell keys apart.

From the key list's ⋯ menu you can:

ActionWhat it does
Copy keyCopies the full key to your clipboard without showing it on screen. Keys created before secure copy existed have no copy option — rotate them once to enable it.
RotateIssues a new secret for the same key (same name, same scopes). The old secret stops working immediately, and the new one is shown once.
DeleteRevokes the key permanently. Requests using it fail from that moment.

Authenticating a request ​

Send the key as a bearer token on every request to https://<your-workspace>-api.perfox.ai/api/v1/…:

Authorization: Bearer sk_<key>

Each request is checked in this order:

  1. The header must be present and well-formed, and the key must exist — otherwise 401 invalid_api_key.
  2. A key that is no longer active returns 401 revoked_api_key.
  3. The key must carry the scope the endpoint requires — otherwise 403 insufficient_scope, with a message naming the missing scope.
  4. The request must be within the rate limit — otherwise 429 rate_limited, with a Retry-After header. The limit applies per key and across your whole workspace, over a one-minute window.

Routes are deny-by-default: a key can only call endpoints whose scope it was given.

Scopes ​

These are the scopes you can tick when creating a key. A new key starts with Structured document extraction, Read Knowledge Base and Upload & manage Knowledge Base pre-selected (plus Ingest customer memory, which no endpoint uses any more — untick it).

GroupScopeLabel in the Studio
Agentsworkflows:readRead agents
Agentsworkflows:writeCreate & edit agents
Agentsworkflows:publishPublish agents
Knowledge Basekb:readRead Knowledge Base
Knowledge Basekb:writeUpload & manage Knowledge Base
Customerscustomers:readRead customers
Customerscustomers:writeCreate & update customers
Conversationsconversations:readRead conversations & transcripts
Conversationsconversations:writeWrite conversations
Credentialscredentials:readRead provider credentials
Credentialscredentials:writeRegister provider credentials
MCP Serversmcp_servers:readRead MCP tool servers
MCP Serversmcp_servers:writeRegister MCP tool servers
Documentsdocuments:extractStructured document extraction
Analyticsanalytics:readRead analytics
Supportsupport:readRead support tickets
Supportsupport:writeRaise & reply to support tickets
Webhookswebhooks:readRead webhook subscriptions
Webhookswebhooks:writeManage webhook subscriptions

Endpoints by scope ​

Every path below is under https://<your-workspace>-api.perfox.ai.

ScopeEndpointsGuide
workflows:readGET /api/v1/agents, GET /api/v1/agents/{id}API Explorer
workflows:writePOST /api/v1/agents, PATCH /api/v1/agents/{id}, POST /api/v1/agents/from-spec, POST /api/v1/agents/generateAPI Explorer
workflows:publishPOST /api/v1/agents/{id}/publishAPI Explorer
customers:readGET /api/v1/customers, GET /api/v1/customers/{id}API Explorer
customers:writePOST /api/v1/customers, PATCH /api/v1/customers/{id}, POST /api/v1/customer/linkAPI Explorer
conversations:readGET /api/v1/conversations, GET /api/v1/conversations/{id}, GET /api/v1/conversations/{id}/events, GET /api/v1/cases, GET /api/v1/calls, GET /api/v1/calls/{id}, GET /api/v1/conversations/{id}/recordings, GET /api/v1/messages, GET /api/v1/messages/{id}Conversations, Cases, Calls, Messages
conversations:writePOST /api/v1/outbound, POST /api/v1/messagesOutbound, Messages
kb:readGET /api/v1/kb/files, GET /api/v1/kb/files/{id}, GET /api/v1/kb/files/{id}/download, GET /api/v1/kb/folders, POST /api/v1/kb/searchKnowledge Base
kb:writePOST /api/v1/kb/files, DELETE /api/v1/kb/files/{id}, POST /api/v1/kb/files/{id}/move, POST /api/v1/kb/folders, PATCH /api/v1/kb/folders/{id}, DELETE /api/v1/kb/folders/{id}Knowledge Base
credentials:readGET /api/v1/credentials, GET /api/v1/credentials/{id}, GET /api/v1/credentials/{id}/resourcesCredentials
credentials:writePOST /api/v1/credentialsCredentials
mcp_servers:readGET /api/v1/mcp-servers, GET /api/v1/mcp-servers/{id}API Explorer
mcp_servers:writePOST /api/v1/mcp-servers, PATCH /api/v1/mcp-servers/{id}API Explorer
documents:extractPOST /api/v1/documents/extract_structuredbelow
analytics:readGET /api/v1/analytics/summary, GET /api/v1/analytics/conversations-over-time, GET /api/v1/analytics/channel-breakdown, GET /api/v1/billing/credits, GET /api/v1/billing/usageAnalytics & Usage
support:readGET /api/v1/support/tickets, GET /api/v1/support/tickets/{id}Support Tickets
support:writePOST /api/v1/support/tickets, POST /api/v1/support/tickets/{id}/replySupport Tickets
webhooks:readGET /api/v1/webhook-subscriptionsMessages & Webhooks
webhooks:writePOST /api/v1/webhook-subscriptions, PATCH /api/v1/webhook-subscriptions/{id}, DELETE /api/v1/webhook-subscriptions/{id}, POST /api/v1/webhook-subscriptions/{id}/testMessages & Webhooks

The machine-readable description of all of these is served, without authentication, at GET /api/v1/openapi.json on your API host.

Structured document extraction ​

POST /api/v1/documents/extract_structured takes a document and a JSON Schema and returns the document's contents shaped to that schema. Send it as multipart/form-data:

FieldRequiredWhat
fileyesPDF, DOCX, TXT, PNG, JPEG or WEBP. Anything else returns 415 unsupported_mime.
schemayesA JSON Schema, as a JSON string. Missing → 400 missing_schema; not a JSON object → 400 bad_schema.
promptnoExtra instructions for the extraction.

Worked example — uploading a file to the Knowledge Base ​

Setup: Asha, an admin at Acme Support, wants her deployment pipeline to push the latest product manual into Perfox automatically. She creates a key with only the Upload & manage Knowledge Base scope and stores it as PERFOX_API_KEY.

Action: Her pipeline runs:

bash
curl -X POST https://acme-support-api.perfox.ai/api/v1/kb/files \
  -H "Authorization: Bearer $PERFOX_API_KEY" \
  -F "file=@product-manual-v3.pdf" \
  -F "folder_id=fld_abc123"

Result: Perfox returns 201 with the new file's id and status: "pending". Indexing runs in the background; the pipeline polls GET /api/v1/kb/files/{id} until the status is active.

What just happened: The key carried kb:write, so it passed the scope check. Had the pipeline called POST /api/v1/outbound, it would have received 403 insufficient_scope — the key simply cannot do that, whoever holds it.

Error codes ​

HTTPCodeMeaning
400invalid_requestThe body or query parameters failed validation; message names the field.
401invalid_api_keyKey missing, malformed, or does not match.
401revoked_api_keyKey exists but is no longer active.
403insufficient_scopeKey is valid but lacks the scope this endpoint requires.
404not_foundThe id in the path does not exist in your workspace.
429rate_limitedToo many requests; wait for the number of seconds in Retry-After.

Every error body has the same shape: { "error": "<code>", "message": "<detail>" }, sometimes with extra fields that are documented on the endpoint.

Next steps ​

  • Knowledge Base — upload, search and organise documents from your own systems.
  • Messages & Webhooks — send WhatsApp messages and receive inbound messages on your endpoint.
  • Site Management — the separate keying for the embeddable chat widget.