Messaging API overview

Get a credential, make your first call, and see every texting endpoint.

The SUZKO Phone Messaging API lets your own software send texts from your business numbers, read them back, and get events when they're delivered or answered. API texts go through the same path as texts you send from the dashboard: same included texts, same spend limit, same texting registration, same opt-out list.

1. Get a credential

Open the developer console at /dashboard/developers, also reachable from Profile → Developers. API tokens, machine keys and webhooks all live there. You'll need two-factor authentication on, and the console asks for a code from your authenticator app before it creates anything.

  • For a server, an integration or webhooks: a machine key (szk_mk_…). Create a service account under Machine keys, give it the scopes it needs, then create its key. Owner only. Machine keys don't expire.
  • For your own scripts: a personal token (szk_pat_…). Create one under Personal tokens. It expires in 30 days by default (90 at most) and stops working if your access to the account changes.

The full secret is shown once. Copy it straight into your server's secret store. The differences, scopes and revocation rules are in API credentials.

Keep credentials on your server. Never put one in a mobile app, a browser, or a public repository: anyone holding it can text as your business and spend against your account.

2. Make a call

Base URL:

TEXT
https://www.suzko.com/api/v1

Use www.suzko.com. The bare suzko.com redirects there, and most HTTP clients drop the Authorization header (and turn a POST into a GET) when they follow a redirect.

Send the credential as a bearer token. List your numbers first (scope numbers:read):

Shell
curl https://www.suzko.com/api/v1/numbers \
  -H "Authorization: Bearer szk_mk_YOUR_MACHINE_KEY"
JSON
{
  "success": true,
  "data": [
    {
      "object": "phone_number",
      "id": "pn_Ht6Wq2Kz9LmB",
      "number": "+13175550100",
      "type": "local",
      "displayName": "Front desk",
      "canText": true,
      "reason": null
    }
  ],
  "meta": { "nextCursor": null }
}

Then send a text (scope messages:send):

Shell
curl https://www.suzko.com/api/v1/messages \
  -H "Authorization: Bearer szk_mk_YOUR_MACHINE_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2e0a-order-1042" \
  -d '{"to": "+13175550123", "from": "pn_Ht6Wq2Kz9LmB", "body": "Your order #1042 is ready for pickup."}'

A 202 with "status": "queued" means it's accepted and on its way. Real texts cost real money: test against your own phone first.

The console's Quick start has a ready-to-run send command with your number filled in.

Endpoints

Every request and response body is JSON. Send Content-Type: application/json on requests with a body.

MethodPathScopeWhat it does
POST/messagesmessages:sendSend one text
POST/messages/batchmessages:sendSend up to 1,000 texts
GET/messagesmessages:readList messages, newest first
GET/messages/{id}messages:readOne message
GET/numbersnumbers:readYour numbers and whether each can text
GET/usageusage:readThis month's texting usage
GET/webhookswebhooks:manageThe endpoints this credential created
POST/webhookswebhooks:manageAdd an endpoint
GET/webhooks/{id}webhooks:manageOne endpoint and its newest 50 deliveries
DELETE/webhooks/{id}webhooks:manageRemove an endpoint
POST/webhooks/{id}/verifywebhooks:manageSend the verification challenge again
POST/webhooks/{id}/rotate-secretwebhooks:manageNew signing secret, 24-hour overlap
POST/webhooks/{id}/testwebhooks:manageQueue a test event
POST/webhooks/{id}/deliveries/{deliveryId}/replaywebhooks:manageDeliver a finished delivery again

Every texting scope needs an active SUZKO Phone plan on the account: without one, those routes answer 403 plan_required. If the plan is active but Business Phone was never set up, sends and /usage answer 404 not_found and lists come back empty.

Responses in short

JSON
{ "success": true, "data": { } }
JSON
{
  "success": false,
  "error": "This recipient has opted out of texts from your business.",
  "code": "opted_out",
  "requestId": "req_7Hq2Lm9Xc4Vb8Nz1Kd5Rt3Wy"
}
  • Branch on code, not on error.
  • Every response carries X-Request-Id. Quote it to support.
  • Lists return data: [...] and meta.nextCursor; 25 per page by default, 100 at most.
  • Timestamps are RFC 3339 UTC. Money is { "amount": "50.00", "currency": "USD" }.

The full code table, rate limits and headers are in Errors and limits.