API Reference
The JoltSMS REST API lets you manage phone numbers, read SMS messages, control billing, configure notifications, and collaborate with team members. All requests use the base URL https://api.joltsms.com/v1 and require an Authorization: Bearer jolt_sk_xxx header.
OpenAPI Specification
Download the machine-readable OpenAPI spec to auto-generate API clients, create Custom GPT Actions, or build LangChain toolkits.
https://api.joltsms.com/openapi.jsonCommon Patterns
Cursor Pagination
All list endpoints return paginated results with the same envelope. Pass the cursor value from the previous response to fetch the next page. limit defaults to 20 (capped at 10 for API key authentication).
{
"data": [ ... ],
"meta": {
"hasMore": true,
"nextCursor": "MjAyNS0wNi0xNVQxMjowMDowMC4wMDBafGFiY2QxMjM0",
"total": 42,
"limit": 20
}
}Error Format
Errors follow a consistent JSON structure across all endpoints.
{
"error": "NOT_FOUND",
"message": "Number not found or you do not have access"
}Rate Limit Headers
Every response includes rate limit headers. API key requests are limited to 120 requests per minute.
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed per window (120 for API keys) |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | Seconds remaining until the rate limit window resets |
Numbers
Manage your dedicated phone numbers. Each number is a real-SIM U.S. number that receives inbound SMS.
/v1/numbersList your phone numbers with optional status and scope filtering.
| Parameter | Type | Description |
|---|---|---|
| scope | string | Filter by ownership: "all" (default), "owned", or "shared". |
| status | string | Filter by status: active, provisioning, releasing, released, failed, suspended, cancelled. |
| cursor | string | Pagination cursor from a previous response. |
| limit | number | Results per page. Default 20, max 10 for API keys. |
/v1/numbers/rentProvision a new phone number. This creates a Stripe subscription and begins the provisioning process.
| Parameter | Type | Description |
|---|---|---|
| areaCode | string | Preferred 3-digit U.S. area code (e.g., "609"). Optional -- omit for any available number. |
| preferredAreaCode | boolean | If true, falls back to any available number when the requested area code is unavailable. Default false. |
| autoRenew | boolean | Enable auto-renewal at end of billing cycle. Default true. |
/v1/numbers/:idRetrieve a single number by ID, including message counts, subscription details, and team access info.
/v1/numbers/:idUpdate a number's notes or tags.
| Parameter | Type | Description |
|---|---|---|
| notes | string | Free-text notes about this number. |
| tags | string[] | Array of tag strings for categorization. |
Example
curl -X GET "https://api.joltsms.com/v1/numbers?scope=owned&status=active" \
-H "Authorization: Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"Response:
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phoneNumber": "+16094130666",
"status": "ACTIVE",
"serviceName": "Any Service",
"tags": ["primary", "otp"],
"notes": "Used for PayPal verification",
"createdAt": "2025-06-15T12:00:00.000Z",
"rentedAt": "2025-06-15T12:05:00.000Z",
"expiresAt": "2025-07-15T12:05:00.000Z",
"messageCount": 23,
"unreadCount": 2,
"lastMessageAt": "2025-06-20T08:30:00.000Z",
"isShared": false,
"accessRole": "OWNER"
}
],
"meta": {
"hasMore": false,
"total": 1,
"limit": 20
}
}Messages
Read inbound SMS messages across all your numbers (owned and shared). Messages from vendor systems are automatically filtered out.
/v1/messagesList SMS messages with optional filtering by number, sender, recipient, or date.
| Parameter | Type | Description |
|---|---|---|
| numberId | string | Filter to messages for a specific number (UUID). |
| from | string | Filter by sender phone number. |
| to | string | Filter by recipient phone number. |
| since | string | ISO 8601 datetime -- only return messages after this time. |
| cursor | string | Pagination cursor from a previous response. |
| limit | number | Results per page. Default 20, max 10 for API keys. |
/v1/messages/searchFull-text search across message bodies. Supports all the same filters as the list endpoint.
| Parameter | Type | Description |
|---|---|---|
| q* | string | Search query (1-100 characters). |
| numberId | string | Limit search to a specific number. |
| cursor | string | Pagination cursor. |
| limit | number | Results per page. Default 20, max 50. |
/v1/messages/:idRetrieve a single message by ID.
/v1/messages/:id/readMark a single message as read.
/v1/messages/mark-all-readMark all messages as read, optionally scoped to a single number.
| Parameter | Type | Description |
|---|---|---|
| numberId | string | If provided, only mark messages for this number as read. |
Example
curl -X GET "https://api.joltsms.com/v1/messages?numberId=a1b2c3d4-e5f6-7890-abcd-ef1234567890&limit=5" \
-H "Authorization: Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"Response:
{
"data": [
{
"id": "f1e2d3c4-b5a6-7890-1234-567890abcdef",
"numberId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"number": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"phoneNumber": "+16094130666"
},
"from": "+18005551234",
"to": "+16094130666",
"body": "Your verification code is 847293. Do not share this with anyone.",
"parsedCode": "847293",
"isRead": false,
"receivedAt": "2025-06-20T08:30:00.000Z",
"ingestedAt": "2025-06-20T08:30:01.000Z"
}
],
"meta": {
"hasMore": false,
"nextCursor": null,
"total": 1,
"limit": 5,
"filters": {
"numberId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
}Billing
Inspect subscriptions, invoices, and payment methods. Billing is handled through Stripe with 30-day cycles aligned to your SMS provider.
/v1/billing/subscriptionsList all subscriptions for your account, including billing health status.
/v1/billing/subscriptions/:id/auto-renewToggle auto-renewal for a subscription. Disabling auto-renew schedules cancellation at the end of the current billing period.
| Parameter | Type | Description |
|---|---|---|
| enabled* | boolean | Set to true to enable auto-renew, false to cancel at period end. |
/v1/billing/invoicesList invoices for your account. Includes amount, status, and PDF download links. Uses Stripe-style pagination (not cursor-based).
| Parameter | Type | Description |
|---|---|---|
| startingAfter | string | Stripe invoice ID to paginate after (e.g., "in_xxx"). Fetch the next page by passing the last invoice ID from the previous response. |
| status | string | Filter by invoice status: "draft", "open", "paid", "void", or "uncollectible". |
| limit | number | Results per page. Default 20, max 100. |
/v1/billing/payment-methodsList saved payment methods. Returns last-4 digits, brand, and expiration.
Example
curl -X POST "https://api.joltsms.com/v1/billing/subscriptions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/auto-renew" \
-H "Authorization: Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-H "Content-Type: application/json" \
-d '{ "enabled": false }'Response:
{
"success": true
}Billing health states
Subscriptions include a billingHealth field that summarizes the payment state: healthy, payment_failing, suspended, ending, canceled, or setup_required. SMS reception is active for healthy, payment_failing, and ending.
Notifications
Configure multi-channel notification delivery for SMS events, billing alerts, and number lifecycle changes. Supported channels: Slack, Discord, Email, Telegram, and custom Webhooks (HMAC-SHA256 signed).
Endpoints
/v1/notifications/endpointsList all notification endpoints for your account. Optionally filter by number or endpoint type.
| Parameter | Type | Description |
|---|---|---|
| numberId | string | Filter endpoints associated with a specific number. |
| type | string | Filter by type: slack, discord, email, telegram, webhook. |
/v1/notifications/endpointsCreate a new notification endpoint. Webhook URLs are validated against SSRF.
| Parameter | Type | Description |
|---|---|---|
| type* | string | Endpoint type: slack, discord, email, telegram, or webhook. |
| name* | string | Display name for the endpoint. |
| config* | object | Channel-specific configuration (e.g., webhookUrl for Slack, email address for email). |
/v1/notifications/endpoints/:idUpdate an existing notification endpoint's name, config, or active status.
/v1/notifications/endpoints/:idDelete a notification endpoint. System-managed endpoints (auto-created email) cannot be deleted.
Rules
Rules bind events to endpoints. You can create account-level defaults or per-number overrides. Limits: 15 endpoints per user, 10 rules per number.
/v1/notifications/rulesList notification rules. Filter by number, event type, or endpoint.
| Parameter | Type | Description |
|---|---|---|
| numberId | string | Filter rules for a specific number. |
| event | string | Filter by event type (e.g., SMS_RECEIVED, NUMBER_EXPIRING_7D). |
| endpointId | string | Filter rules for a specific endpoint. |
| enabled | boolean | Filter by enabled/disabled status. |
/v1/notifications/rulesCreate a notification rule linking an event to an endpoint. Omit numberId for account-level defaults.
| Parameter | Type | Description |
|---|---|---|
| endpointId* | string | The endpoint to deliver notifications to. |
| event* | string | Event type: SMS_RECEIVED, NUMBER_EXPIRING_7D, NUMBER_EXPIRING_1D, BILLING_ISSUE. |
| numberId | string | Scope rule to a specific number. Omit for account-level default. |
| enabled | boolean | Whether the rule is active. Default true. |
/v1/notifications/rules/:idUpdate a rule's enabled status or event binding.
/v1/notifications/rules/:idDelete a notification rule.
Delivery Logs
/v1/notifications/attemptsView delivery attempt history. Useful for debugging failed notifications.
| Parameter | Type | Description |
|---|---|---|
| endpointId | string | Filter attempts for a specific endpoint. |
| event | string | Filter by event type. |
| status | string | Filter by delivery status: success, failed, pending. |
| cursor | string | Pagination cursor. |
| limit | number | Results per page. |
Team
Share number access with other JoltSMS users. Invite team members with VIEWER (read-only) or MANAGER (configuration and team management) roles. Invitations expire after 7 days.
Team endpoints require the caller to be the owner of the number (except for accepting/declining invitations). Both session and API key authentication are supported.
/v1/team/inviteInvite a user to access a number. Sends an email invitation with a 7-day expiry.
| Parameter | Type | Description |
|---|---|---|
| numberId* | string | UUID of the number to share access to. |
| email* | string | Email address of the user to invite. |
| role | string | Role to assign: "VIEWER" (default) or "MANAGER". |
/v1/team/:numberId/membersList all team members for a number, including pending invitations.
/v1/team/:numberId/members/:userId/roleUpdate a team member's role.
| Parameter | Type | Description |
|---|---|---|
| role* | string | "VIEWER" or "MANAGER". |
/v1/team/:numberId/members/:userIdRemove a team member's access to a number.
Example
curl -X POST "https://api.joltsms.com/v1/team/invite" \
-H "Cookie: better-auth.session_token=..." \
-H "Content-Type: application/json" \
-d '{ "numberId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "email": "[email protected]", "role": "VIEWER" }'Response:
{
"success": true,
"invitationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"message": "Invitation sent successfully"
}HTTP Status Codes
The API uses standard HTTP status codes to indicate the outcome of each request.
| Code | Meaning |
|---|---|
| 200 | Request succeeded. |
| 201 | Resource created (e.g., new subscription, new endpoint). |
| 400 | Bad request -- invalid parameters or request body. |
| 401 | Unauthorized -- missing, invalid, expired, or revoked API key. |
| 402 | Payment required -- subscription creation needs valid payment or 3DS confirmation. |
| 403 | Forbidden -- insufficient permissions or API key used on session-only route. |
| 404 | Resource not found or you do not have access. |
| 409 | Conflict -- duplicate idempotency key or resource already exists. |
| 429 | Too many requests -- rate limit exceeded (120/min for API keys). |
| 500 | Internal server error. If persistent, contact support. |