Phone numbers
Finds, buys, and releases US phone numbers for texting. $1.60 per number per month. The base URL is https://www.motor.dev/phone_numbers, and the OpenAPI 3.1 specification describes each endpoint.
Sign in to try the API here with one of your team's keys. Requests use that key's permissions and spending limit. Standard charges apply.
Buying a number
Buy a US local or toll-free number in one call. Set your criteria, and Motor buys the first match:
curl https://api.motor.dev/phone_numbers/numbers \
-H "Authorization: Bearer $MOTOR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"type": "local", "area_code": "415", "label": "Order updates"}'
To choose a specific number, search first, then buy it by its phone_number. If it's no longer available, Motor returns 409 number_unavailable without charging you or buying a substitute.
curl "https://api.motor.dev/phone_numbers/available_numbers?region=CA&contains=777" \
-H "Authorization: Bearer $MOTOR_KEY"
Search filters: type (local or toll_free), area_code, region (a state or DC, local numbers only), contains (1 to 10 digits), and limit (up to 50). Toll-free prefixes are 833, 844, 855, 866, 877, and 888. Motor doesn't sell 800 numbers.
Most numbers are active when you receive the response. A number may be pending while the carrier confirms it. Poll GET /numbers/pn_... until it's active or failed. Failed orders aren't charged. If a request times out, retry it with the same Idempotency-Key: Motor won't buy a second number.
Test mode. Send Motor-Mode: test to search and buy fictional numbers, such as +14155550100, for free. Test numbers activate immediately. To test a failed order, use "contains": "0000" to get a pending number that fails after 10 seconds.
Pricing, billing, and limits
Every number costs $1.60 a month, local or toll-free. There's no setup fee. Test numbers are free.
- Billing starts when the number becomes active and renews on the same day each month. A number activated on the 31st renews on the last day of shorter months.
- Rent is charged to the account associated with the key that bought the number. To change the key, set
billing_key_id. Changes take effect next month. - A purchase returns
402 spending_limit if the first month would exceed the key's monthly spending limit. Renewals continue even if they exceed the limit. They count toward the limit and spending alerts. - Releasing a number stops future charges. Unused time isn't refunded.
| Limit | Default, per team and mode |
|---|
| Numbers (excluding released and failed) | 100 |
| Purchases | 20 an hour |
| Searches | 10 a second |
To raise a limit, contact support@motor.dev.
Releasing a number
Release an active number you no longer need:
curl -X DELETE https://api.motor.dev/phone_numbers/numbers/pn_8Kq2vLxN4cT7 \
-H "Authorization: Bearer $MOTOR_KEY"
The number becomes releasing, then released once the carrier confirms. Release is permanent. The carrier can reassign the number. Released number records remain available for 90 days.
If an SMS sender uses the number, the API returns 409 number_in_use with the sender ID in resource_id. Delete the sender, wait until the number's used_by is null, then release it.
Search
GET/phone_numbers/available_numbers
Search available numbers
Returns matching numbers. Results aren't paginated or reserved. Refine the filters to change the results. No matches returns an empty list with 200. The default limit is 10 searches per second, per team and mode.
Responses
200The matching numbers.
{
"data": [
{
"phone_number": "+14155550123",
"type": "local",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"monthly_price_usd": "1.60"
}
]
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
422Invalid filter or unsupported 800 prefix (unsupported_number).
{
"error": {
"code": "unsupported_number",
"message": "Motor doesn't sell 800 numbers. Use another toll-free prefix: 833, 844, 855, 866, 877, 888."
}
}
429Search limit reached. Wait the number of seconds in Retry-After before retrying.
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Retry after 2 seconds."
}
}
503Motor's number provider couldn't complete the search. Retry.
{
"error": {
"code": "temporarily_unavailable",
"message": "Motor's number provider couldn't complete the search. Retry in a few seconds."
}
}
Numbers
POST/phone_numbers/numbers
Buy a number
Buys a specific number or the first match for your criteria, trying up to three candidates. Most numbers are active in the response. If pending, poll until active or failed. Billing starts on activation. Motor never substitutes another number for a specific number you request. An Idempotency-Key is required; retry with the same key to avoid buying a second number.
Responses
201The number, active or pending.
{
"id": "pn_8Kq2vLxN4cT7",
"phone_number": "+14155550123",
"type": "local",
"status": "active",
"label": "Order updates",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"used_by": null,
"monthly_price_usd": "1.60",
"billing_key_id": "key_BWBeN28Vb7cMEx7Ym8AUzs",
"paid_through": "2026-11-09T18:22:04Z",
"failure_reason": null,
"created_at": "2026-10-09T18:22:01Z",
"activated_at": "2026-10-09T18:22:04Z",
"released_at": null
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
402The first month would exceed the key's monthly spending limit.
{
"error": {
"code": "spending_limit",
"message": "The $1.60 charge for the first month would exceed this key's monthly spending limit. Raise the limit on the API keys page."
}
}
409The number is unavailable (number_unavailable), the team's number limit was reached (quota_exceeded), or the idempotency key was used for a different request.
{
"error": {
"code": "number_unavailable",
"message": "+14155550123 is no longer available. You weren't charged. Search for another number."
}
}
422A field isn't valid, no number matches the criteria (no_numbers_available), or the number is an 800 number (unsupported_number).
{
"error": {
"code": "no_numbers_available",
"message": "No numbers match these criteria. Try removing contains or region."
}
}
429The team's hourly purchase limit was reached.
{
"error": {
"code": "rate_limited",
"message": "Your team has reached its limit of 20 number purchases per hour. Retry later."
}
}
503Motor's number provider couldn't accept the order. You weren't charged.
{
"error": {
"code": "temporarily_unavailable",
"message": "Motor's number provider couldn't accept the order. You weren't charged. Retry in a few minutes."
}
}
GET/phone_numbers/numbers
List your numbers
Lists the team's numbers in the selected mode, oldest first. Includes all statuses except released by default. Released and failed number records remain available for 90 days.
Responses
200A page of numbers.
{
"data": [
{
"id": "pn_8Kq2vLxN4cT7",
"phone_number": "+14155550123",
"type": "local",
"status": "active",
"label": "Order updates",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"used_by": null,
"monthly_price_usd": "1.60",
"billing_key_id": "key_BWBeN28Vb7cMEx7Ym8AUzs",
"paid_through": "2026-11-09T18:22:04Z",
"failure_reason": null,
"created_at": "2026-10-09T18:22:01Z",
"activated_at": "2026-10-09T18:22:04Z",
"released_at": null
}
],
"next_cursor": null
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
422A field or parameter isn't valid.
{
"error": {
"code": "invalid_field",
"message": "`area_code` must be three digits, such as 415."
}
}
GET/phone_numbers/numbers/{id}
Read a number
Returns a number. Poll a pending number here until it's active or failed.
Responses
200The number.
{
"id": "pn_8Kq2vLxN4cT7",
"phone_number": "+14155550123",
"type": "local",
"status": "active",
"label": "Order updates",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"used_by": null,
"monthly_price_usd": "1.60",
"billing_key_id": "key_BWBeN28Vb7cMEx7Ym8AUzs",
"paid_through": "2026-11-09T18:22:04Z",
"failure_reason": null,
"created_at": "2026-10-09T18:22:01Z",
"activated_at": "2026-10-09T18:22:04Z",
"released_at": null
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
404The number wasn't found for your team in this mode, or it was released or failed more than 90 days ago.
{
"error": {
"code": "not_found",
"message": "The number doesn't exist."
}
}
PATCH/phone_numbers/numbers/{id}
Change a number's label or billing key
Updates label and billing_key_id. Billing key changes take effect next month.
Request body{
"label": "Support line"
}
Responses
200The changed number.
{
"id": "pn_8Kq2vLxN4cT7",
"phone_number": "+14155550123",
"type": "local",
"status": "active",
"label": "Support line",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"used_by": null,
"monthly_price_usd": "1.60",
"billing_key_id": "key_BWBeN28Vb7cMEx7Ym8AUzs",
"paid_through": "2026-11-09T18:22:04Z",
"failure_reason": null,
"created_at": "2026-10-09T18:22:01Z",
"activated_at": "2026-10-09T18:22:04Z",
"released_at": null
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
404The number wasn't found for your team in this mode, or it was released or failed more than 90 days ago.
{
"error": {
"code": "not_found",
"message": "The number doesn't exist."
}
}
409The number changed during the update. Read it again and retry.
{
"error": {
"code": "revision_conflict",
"message": "The number changed during the update. Read it again and retry."
}
}
412If-Match isn't the number's current ETag.
{
"error": {
"code": "revision_conflict",
"message": "The number changed since you read it. Read it again and retry with the new ETag."
}
}
422A field or parameter isn't valid.
{
"error": {
"code": "invalid_field",
"message": "`area_code` must be three digits, such as 415."
}
}
DELETE/phone_numbers/numbers/{id}
Release a number
Releases an unused active number. Its status becomes releasing, then released once the carrier confirms. Release is permanent, and the carrier can reassign the number. Unused time isn't refunded.
Responses
200The number with status releasing.
{
"id": "pn_8Kq2vLxN4cT7",
"phone_number": "+14155550123",
"type": "local",
"status": "releasing",
"label": "Order updates",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"sms": true,
"mms": true,
"voice": false
},
"used_by": null,
"monthly_price_usd": "1.60",
"billing_key_id": "key_BWBeN28Vb7cMEx7Ym8AUzs",
"paid_through": "2026-11-09T18:22:04Z",
"failure_reason": null,
"created_at": "2026-10-09T18:22:01Z",
"activated_at": "2026-10-09T18:22:04Z",
"released_at": null
}
401The key is missing or incorrect.
{
"error": {
"code": "unauthorized",
"message": "This API key is invalid or has been revoked."
}
}
403The key can't use phone numbers, or it's a publishable key.
{
"error": {
"code": "forbidden",
"message": "This key cannot access this API. Update its permissions on the API keys page."
}
}
404The number wasn't found for your team in this mode, or it was released or failed more than 90 days ago.
{
"error": {
"code": "not_found",
"message": "The number doesn't exist."
}
}
409A Motor resource uses the number (number_in_use, with resource_id), or the number isn't active (invalid_state).
{
"error": {
"code": "number_in_use",
"message": "Delete SMS sender sms_snd_1 before releasing this number.",
"resource_id": "sms_snd_1"
}
}
412If-Match isn't the number's current ETag.
{
"error": {
"code": "revision_conflict",
"message": "The number changed since you read it. Read it again and retry with the new ETag."
}
}