Skip to content

HTTP API

Complete workflows with the Phonekit API

The API owns authorization, entitlements, provisioning and durable delivery. Your caller owns SMS polling, matching, deadlines and cancellation. The SDK wraps these same HTTP operations.

Authenticate deliberately

Create a credential in Settings → Automation. Select permissions and exact line grants separately for message reads and management. Existing credentials retain messages:read only. No credential administration API is required.

Send Authorization: Bearer $PHONEKIT_API_KEY over HTTPS. GET /api/v1/me returns the organization, connection identity, permissions, readable numbers and managedNumberIds. A number visible to a person is not automatically readable through a credential.

Download the OpenAPI specification for complete request and response schemas.

Discover before acting

Method and pathPurpose
GET /api/v1/meConnection identity, permissions and explicit scopes
GET /api/v1/number-typesSupported types and actual receive/send/voice capabilities
GET /api/v1/allowancePlan, usage and remaining capacity; requires numbers:manage
GET /api/v1/numbersReadable lines
GET /api/v1/numbers/{numberRef}Exact authorized line metadata and readiness
GET /api/v1/membersEligible member IDs/names/roles for assignment/sharing; requires numbers:manage
GET /api/v1/inventory?areaCode=415Supported available lines; requires numbers:manage

Scroll horizontally to see all columns.

Starter, Team and Scale include programmatic surfaces, authorized number management and webhooks, with 30-day default message retention. See pricing for included Standard/Mobile numbers, members, separate monthly SMS pools and overage rates. Workspace overrides replace plan defaults; purchased number additions extend capacity and the matching SMS pool. Membership limits apply to people who have joined, including owners and administrators. API keys and agents do not consume member places. subscription reports USD customer fees and monthly SMS capacity. sms reports the billing-period boundaries, per-class usage and estimated overage; exceeding the pool does not block delivery. Mobile capacity is reported as mobileNumbers. Supplier-cost limits are separate provisioning controls; nullable supplier-cost fields do not mean customer pricing is free.

Use number-type capabilities and inventory to choose a supported number for the workflow. Number acceptance by a target service is not guaranteed. readiness.canReceive requires active status; local fixtures are identified as simulated.

Acquire, configure and release

POST /api/v1/numbers requires numbers:manage, a UUID requestId (or matching Idempotency-Key header), explicit sharing, memberIds, and grantReadAccess choice:

Acquire a selected supported lineJSON
{
  "requestId": "90af27b0-275b-4c82-9f10-69d55f61203d",
  "phoneNumber": "+14155550101",
  "label": "QA account",
  "sharing": "restricted",
  "memberIds": [],
  "grantReadAccess": true,
  "purpose": "Invitation acceptance"
}

Save the UUID before sending. Retry with the same UUID and identical input; a changed body returns idempotency_conflict. A successful response contains operationId, numberId and statusUrl. It records an acquisition; it does not claim activation has completed. GET /api/v1/operations/{operationId} returns pending/completed/failed status, readiness and retry timing. POST /api/v1/numbers/{numberRef}/recheck reconciles a pending acquisition without repurchasing.

Capacity is reserved atomically for pending purchases. Ambiguous provider outcomes keep their reservation until reconciled. Optional maxSetupCostMinor and maxMonthlyCostMinor are explicit price ceilings; an unavailable quote cannot satisfy a ceiling.

PATCH /api/v1/numbers/{numberRef} accepts label, purpose, assignedToUserId, or access: {sharing, memberIds}. Assignment is metadata; sharing governs human access. Owners and admins retain access. Management grants do not grant message reads.

DELETE /api/v1/numbers/{numberRef} saves an authorized release intent for an active selected line and attempts provider release. It returns {ok:true,numberId,status} where status is released or release_pending. Follow GET /api/v1/numbers/{numberRef} for release.status, release.requestedAt and a safe retry detail. A pending release retains capacity until the provider confirms it. Phonekit retries durable intent even if the original connection is subsequently revoked. Retained messages keep their original receipt-based expiry. New write requests still check current permissions and creator membership.

Read fresh receipts immediately

Mark before your application requests SMS:

Capture a position, then trigger the application's SMS requestShell
curl --silent --show-error --fail-with-body \
  --header "Authorization: Bearer ${PHONEKIT_API_KEY}" \
  "https://www.phonekit.io/api/v1/numbers/${PHONEKIT_NUMBER_ID}/cursor"

Then call GET /api/v1/numbers/{numberRef}/messages/after?after={cursor}&limit=25. Reads return promptly in ascending receipt order:

Empty immediate resultJSON
{"data": [], "cursor": "c_djE6MTAw", "hasMore": false}

Nonempty data contains messages with id, numberId, sender, body, otp, links and receivedAt. The cursor advances past the last returned receipt; an empty read leaves it unchanged. hasMore indicates another page existed at read time. Limits are 1–100. Preserve opaque cursors unchanged.

The caller decides matching, interval, deadline, cancellation, resends and parallel work. Inspect unrelated receipts deliberately and save progress. SDK/CLI convenience waits repeat immediate reads locally. MCP tools return promptly. Phonekit has no customer wait sessions, concurrency packaging or test scheduler. Normal API rate limits are operational controls.

Retained messages and selected subscriptions

GET /api/v1/messages?numberId=…&limit=10&cursor=… returns newest-first retained pages {data,nextCursor}. GET /api/v1/messages/{messageId} reads the exact retained receipt, including the ID from a webhook event. Scope and retention apply equally to full content and OTP extraction.

Method and pathPermission
GET /api/v1/webhooks and GET /api/v1/webhooks/{id}webhooks:manage
POST /api/v1/webhooks with {url,numberIds}webhooks:manage
PATCH /api/v1/webhooks/{id} with URL or replacement number IDswebhooks:manage
DELETE /api/v1/webhooks/{id}webhooks:manage
GET /api/v1/deliveries and GET /api/v1/deliveries/{id}diagnostics:read
POST /api/v1/deliveries/{id}/retrywebhooks:manage

Scroll horizontally to see all columns.

Subscribe explicit management-scoped line IDs to a public HTTPS endpoint. Creation returns the signing secret once. A subscription must be wholly within the connection's selected scope. Legacy subscriptions need an explicit line selection before delivery resumes.

Events use stable IDs and may duplicate. Deduplicate durably; read exact message IDs, and recover gaps with saved inbox cursors. Diagnostics expose sanitized attempt status/categories and retry timing. They omit message text, credentials and destination response bodies. See webhook verification.

Distinguish failures

Errors contain code, safe message, requestId, and applicable retryAfterSeconds. Responses include X-Request-Id; rate-limit responses use Retry-After. No result is evidence that the target service accepted a verification code.

FailureMeaning
401Missing, expired or revoked authentication
403 / permission_requiredExplicit permission or current membership is missing
404Resource outside scope or retention
409 / allowance_exhaustedActive and pending acquisitions consume the line allowance
409 / idempotency_conflictSame UUID with a different acquisition body
409 / pricing_unavailableAn explicit spend ceiling cannot be evaluated
429Operational rate limit; honor retry timing
5xxService failure; bounded retries for safe/idempotent operations

Scroll horizontally to see all columns.

An empty immediate read is successful. SDK timeout, no_match, missing_otp/extraction_failed, ambiguous and cancelled describe caller-side outcomes. Keep message contents and bearer credentials out of shared logs.