Authentication
The JoltSMS API uses API keys to authenticate requests. Include your key as a Bearer token in the Authorization header or send the same key in X-API-Key. API keys can be scoped to personal numbers, selected numbers, or an enterprise contract, so create the narrowest key your integration needs.
Creating API Keys
Generate API keys from the JoltSMS dashboard. Each key is shown only once at creation time -- store it immediately in a secure location.
- 1
Open the Dashboard and navigate to Settings.
- 2
Scroll to the API Keys section.
- 3
Click Create API Key, give it a descriptive name (e.g., "CI Pipeline" or "Claude Agent"), choose an access scope, and optionally enable sensitive capabilities such as SMS replies.
- 4
Copy the key immediately. It will not be shown again.
Key shown once
The full API key is displayed only at creation time. If you lose it, revoke the key and create a new one. You can have up to 5 active keys per account.
Key format
All JoltSMS API keys begin with the prefix jolt_sk_ followed by 32 hexadecimal characters. Example: jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Using API Keys
Pass your API key in the Authorization header as a Bearer token, or in the X-API-Key header. All requests must use HTTPS.
curl
curl -X GET https://api.joltsms.com/v1/numbers \
-H "Authorization: Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"curl with X-API-Key
curl -X GET https://api.joltsms.com/v1/messages \
-H "X-API-Key: jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"JavaScript (fetch)
const response = await fetch("https://api.joltsms.com/v1/numbers", {
headers: {
"Authorization": "Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
},
});
const data = await response.json();
console.log(data);Python (requests)
import requests
response = requests.get(
"https://api.joltsms.com/v1/numbers",
headers={"Authorization": "Bearer jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"},
)
print(response.json())API Key Scopes
API keys are scoped at creation time. Scoped keys affect number and message reads: GET /v1/numbers and GET /v1/messages only return resources allowed by the key.
| Scope | Create fields | Access |
|---|---|---|
| PERSONAL | Omit scope fields or set scopeType to PERSONAL | Personal and team-shared non-enterprise numbers |
| ENTERPRISE_CONTRACT | scopeType plus enterpriseContractId | All numbers in one enterprise contract |
| NUMBER_SET | scopeType plus numberIds | Only the selected numbers |
Existing keys created before scoped keys behave as PERSONAL keys. They continue to work for regular personal and team-shared numbers, but they do not automatically expose enterprise contract lines.
Create a contract-scoped key
curl -X POST https://api.joltsms.com/v1/api-keys \
-H "Content-Type: application/json" \
-b "joltsms_session=YOUR_SESSION_COOKIE" \
-d '{
"name": "Enterprise contract automation",
"scopeType": "ENTERPRISE_CONTRACT",
"enterpriseContractId": "contract_uuid_here"
}'Create a selected-number key
curl -X POST https://api.joltsms.com/v1/api-keys \
-H "Content-Type: application/json" \
-b "joltsms_session=YOUR_SESSION_COOKIE" \
-d '{
"name": "Single workflow key",
"scopeType": "NUMBER_SET",
"numberIds": ["number_uuid_1", "number_uuid_2"]
}'API Key Capabilities
Scopes decide which numbers a key can see. Capabilities decide which sensitive write actions the key can perform. SMS replies are opt-in: a key must include the sms:reply capability to call POST /v1/messages/:id/reply.
Reply capability does not turn JoltSMS into an arbitrary SMS sender. Replies must reference an existing inbound message, the destination is resolved server-side, and destination fields such as to or phone are rejected.
Create a selected-number reply key
curl -X POST https://api.joltsms.com/v1/api-keys \
-H "Content-Type: application/json" \
-b "joltsms_session=YOUR_SESSION_COOKIE" \
-d '{
"name": "Support inbox replies",
"scopeType": "NUMBER_SET",
"numberIds": ["number_uuid_1"],
"capabilities": ["sms:reply"]
}'Rate Limits
API key requests are rate-limited to 120 requests per minute. Session-based requests (from the dashboard) use standard rate limits. Every response includes headers to help you stay within bounds.
| 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 |
Pagination cap
When authenticated with an API key, list endpoints (/v1/numbers, /v1/messages) enforce a maximum page size of 10 results per request. Use cursor-based pagination to retrieve additional pages.
If you exceed the rate limit, the API returns a 429 Too Many Requests response. Back off and retry after the X-RateLimit-Reset time.
Error Responses
Authentication errors return standard HTTP status codes with a JSON body describing the problem.
| Status | Meaning | Common Causes |
|---|---|---|
| 401 | Unauthorized | Missing, invalid, expired, or revoked API key |
| 403 | Forbidden | Using an API key on a session-only endpoint |
| 429 | Too Many Requests | Rate limit exceeded (120 req/min for API keys) |
Error response format
// 401 Unauthorized
{
"error": "UNAUTHORIZED",
"message": "Authentication required"
}
// 403 Session Required
{
"error": "SESSION_REQUIRED",
"message": "This endpoint requires browser session authentication. Bearer tokens cannot be used for this operation."
}
// 429 Rate Limit Exceeded
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded, retry in 42 seconds"
}Session-Only Endpoints
Certain sensitive operations require session authentication (logging in through the dashboard). These endpoints return 403 Forbidden when called with an API key.
| Category | Endpoints | Reason |
|---|---|---|
| API Key Management | GET/POST/DELETE /v1/api-keys | Prevents key escalation |
| Number Management | PUT/DELETE /v1/numbers/:id | Prevents automated release or mutation of active lines |
| Password Change | /auth/change-password | Requires active session verification |
| Two-Factor Authentication | /auth/two-factor/* | Security-critical account settings |
Day-to-day read operations -- listing numbers, reading messages, and checking billing status -- work with API keys. API-key creation/revocation and number management require a browser session.
Security Best Practices
Never commit keys to source control
Add .env and .env.local to your .gitignore. Use a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault, or your CI/CD provider's secret storage) for production deployments.
Use environment variables
Reference your API key from an environment variable rather than hardcoding it in application code.
export JOLTSMS_API_KEY="jolt_sk_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
# Then in your code:
headers: { "Authorization": `Bearer ${process.env.JOLTSMS_API_KEY}` }Rotate keys regularly
Create a new key, update your systems, then revoke the old one. With up to 5 active keys, you can rotate without downtime.
Set expiration dates
When creating a key, set an expiration date appropriate for its use case. Short-lived keys for CI/CD pipelines, longer-lived keys for persistent integrations. Expired keys are automatically rejected.
Use descriptive key names
Name each key after its purpose (e.g., "GitHub Actions Deploy", "Claude MCP Agent", "Monitoring Script"). This makes it easy to identify which key to revoke if one is compromised.
Revoke compromised keys immediately
If you suspect a key has been exposed, revoke it from Settings → API Keys in the dashboard. Revocation takes effect within 60 seconds (the Redis cache TTL).