API reference

API Keys

Create scoped API keys for server-to-server access to /api/external. The full secret is shown once at create or regenerate — store it in your secrets manager.

Dashboard APIs use JWT. Integrations use X-API-Key on /api/external only. Keys cannot call inbox, team, billing, or other dashboard routes. Plan limits cap how many keys you can keep active.

Permission scopes

Assign only the scopes your integration needs. GET /api/api-keys/permissions is a public catalog of the current keys.

  • messages:send — queue outbound text and media via the External API
  • messages:read — fetch delivery status
  • sessions:read — list connected WhatsApp sessions
  • contacts:read — list workspace contacts
  • numbers:check — WhatsApp registration lookup

Rotate keys with regenerate. Revoke immediately if a secret leaks. Every /api/external call is logged for analytics.

GET/api/api-keys/permissions

List permission catalog

Public list of scopes you can assign when creating a key.

URL: https://api.actiwapi.com/api/api-keys/permissions

Auth: None

Code examples

curl -X GET "https://api.actiwapi.com/api/api-keys/permissions" \
  -H "Content-Type: application/json"

Response example200

{
  "success": true,
  "data": [
    { "key": "messages:send", "label": "Send messages", "description": "Queue outbound WhatsApp text and media messages" }
  ]
}

Try in Swagger UI

GET/api/api-keys

List API keys

Metadata only — the secret is never returned after creation.

URL: https://api.actiwapi.com/api/api-keys

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Code examples

curl -X GET "https://api.actiwapi.com/api/api-keys" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{
  "success": true,
  "data": [{
    "id": "uuid",
    "name": "Production server",
    "prefix": "awp_live_",
    "permissions": ["messages:send", "messages:read", "sessions:read"],
    "isActive": true,
    "lastUsedAt": "2026-09-03T10:00:00.000Z"
  }]
}

Try in Swagger UI

POST/api/api-keys

Create API key

Generate a key. Copy apiKey from the response — it is shown once.

URL: https://api.actiwapi.com/api/api-keys

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Request example

{
  "name": "Production server",
  "permissions": ["messages:send", "messages:read", "sessions:read"]
}

Code examples

curl -X POST "https://api.actiwapi.com/api/api-keys" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"
  -d '{  "name": "Production server",  "permissions": ["messages:send", "messages:read", "sessions:read"]}'

Response example201

{
  "success": true,
  "data": {
    "id": "uuid",
    "name": "Production server",
    "keyPrefix": "awp_live_",
    "apiKey": "awp_live_xxxxxxxxxxxxxxxx",
    "permissions": ["messages:send", "messages:read", "sessions:read"]
  }
}

Try in Swagger UI

GET/api/api-keys/{id}

Get API key

Fetch one key’s metadata (no secret).

URL: https://api.actiwapi.com/api/api-keys/{id}

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • id — API key UUID

Code examples

curl -X GET "https://api.actiwapi.com/api/api-keys/{id}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{ "success": true, "data": { "id": "uuid", "name": "Production server", "isActive": true } }

Try in Swagger UI

PUT/api/api-keys/{id}

Update API key

Rename or change permissions without rotating the secret.

URL: https://api.actiwapi.com/api/api-keys/{id}

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • id — API key UUID

Request example

{ "name": "Staging", "permissions": ["sessions:read"] }

Code examples

curl -X PUT "https://api.actiwapi.com/api/api-keys/{id}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"
  -d '{ "name": "Staging", "permissions": ["sessions:read"] }'

Response example200

{ "success": true, "data": { "id": "uuid", "name": "Staging" } }

Try in Swagger UI

POST/api/api-keys/{id}/regenerate

Regenerate secret

Issue a new secret. The previous value stops working immediately.

URL: https://api.actiwapi.com/api/api-keys/{id}/regenerate

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • id — API key UUID

Code examples

curl -X POST "https://api.actiwapi.com/api/api-keys/{id}/regenerate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{ "success": true, "data": { "id": "uuid", "apiKey": "awp_live_newsecret" } }

Try in Swagger UI

POST/api/api-keys/{id}/revoke

Revoke API key

Disable the key without deleting its analytics history.

URL: https://api.actiwapi.com/api/api-keys/{id}/revoke

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • id — API key UUID

Code examples

curl -X POST "https://api.actiwapi.com/api/api-keys/{id}/revoke" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{ "success": true, "data": { "id": "uuid", "isActive": false } }

Try in Swagger UI

DELETE/api/api-keys/{id}

Delete API key

Permanently remove the key.

URL: https://api.actiwapi.com/api/api-keys/{id}

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Path parameters

  • id — API key UUID

Code examples

curl -X DELETE "https://api.actiwapi.com/api/api-keys/{id}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{ "success": true, "data": { "id": "uuid", "deleted": true } }

Try in Swagger UI

GET/api/api-keys/analytics/overview

Usage overview

Aggregate request volume, errors, and latency across keys.

URL: https://api.actiwapi.com/api/api-keys/analytics/overview

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Code examples

curl -X GET "https://api.actiwapi.com/api/api-keys/analytics/overview" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{
  "success": true,
  "data": { "totalRequests": 1280, "errorRate": 0.02, "avgLatencyMs": 42 }
}

Try in Swagger UI

GET/api/api-keys/analytics/requests

Recent requests

Paginated log of /api/external calls.

URL: https://api.actiwapi.com/api/api-keys/analytics/requests

Auth: JWT Bearer

Headers

HeaderValueRequired
AuthorizationBearer {accessToken}Yes
Content-Typeapplication/jsonYes*

Query parameters

  • page — Page number
  • limit — Rows per page

Code examples

curl -X GET "https://api.actiwapi.com/api/api-keys/analytics/requests" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {accessToken}"

Response example200

{
  "success": true,
  "data": [{ "method": "POST", "path": "/api/external/messages/send-text", "status": 202, "durationMs": 18 }]
}

Try in Swagger UI

Error codes

Failed requests return a JSON envelope with success: false and a human-readable message.

{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "phone": "Valid phone number is required"
  }
}
HTTPCodeDescription
400VALIDATION_ERRORRequest body or query failed validation.
401UNAUTHORIZEDMissing or invalid JWT / API key.
403FORBIDDENAuthenticated but lacking permission or entitlement.
403SUBSCRIPTION_INACTIVEAction not allowed on the current plan (including Free after trial). Upgrade or wait for entitlements.
403LIMIT_EXCEEDEDPlan limit reached (sessions, messages, API requests, etc.).
404NOT_FOUNDResource does not exist or is not in your account.
409CONFLICTDuplicate resource or invalid state transition.
429RATE_LIMITEDToo many requests; retry after backoff.
500INTERNAL_ERRORUnexpected server error.
502WHATSAPP_UNAVAILABLEWhatsApp session disconnected or provider error.