curl --request POST \
--url https://api.isnap.ai/v1/lines/assign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"area_code": "<string>",
"inbound_only": true,
"as_test_line": true,
"metadata": {
"crm_account_id": "acc_123"
}
}
'import requests
url = "https://api.isnap.ai/v1/lines/assign"
payload = {
"area_code": "<string>",
"inbound_only": True,
"as_test_line": True,
"metadata": { "crm_account_id": "acc_123" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
area_code: '<string>',
inbound_only: true,
as_test_line: true,
metadata: {crm_account_id: 'acc_123'}
})
};
fetch('https://api.isnap.ai/v1/lines/assign', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.isnap.ai/v1/lines/assign",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'area_code' => '<string>',
'inbound_only' => true,
'as_test_line' => true,
'metadata' => [
'crm_account_id' => 'acc_123'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.isnap.ai/v1/lines/assign"
payload := strings.NewReader("{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.isnap.ai/v1/lines/assign")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.isnap.ai/v1/lines/assign")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "<string>",
"phone_number": "<string>",
"area_code": "<string>",
"country_code": "<string>",
"state": "<string>",
"state_name": "<string>",
"billing_tier": "rental_iphone",
"byod": true,
"inbound_only": true,
"status": "<string>",
"monthly_price": 1,
"stripe_subscription_id": "<string>",
"activated_at": "<string>",
"expires_at": "<string>",
"anniversary_at": "<string>",
"cancel_at": "<string>",
"billing_anchor_at": "<string>",
"next_anchor_at": "<string>",
"pending_variant": {
"inbound_only": true,
"effective_at": "<string>"
},
"created_at": "<string>",
"metadata": {},
"test_line": true,
"shared": true,
"capabilities": "<unknown>",
"fulfillment_status": "<string>"
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}Assign a line
Makes one available line of a kind yours and activates it, in one call.
curl --request POST \
--url https://api.isnap.ai/v1/lines/assign \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"area_code": "<string>",
"inbound_only": true,
"as_test_line": true,
"metadata": {
"crm_account_id": "acc_123"
}
}
'import requests
url = "https://api.isnap.ai/v1/lines/assign"
payload = {
"area_code": "<string>",
"inbound_only": True,
"as_test_line": True,
"metadata": { "crm_account_id": "acc_123" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
area_code: '<string>',
inbound_only: true,
as_test_line: true,
metadata: {crm_account_id: 'acc_123'}
})
};
fetch('https://api.isnap.ai/v1/lines/assign', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.isnap.ai/v1/lines/assign",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'area_code' => '<string>',
'inbound_only' => true,
'as_test_line' => true,
'metadata' => [
'crm_account_id' => 'acc_123'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.isnap.ai/v1/lines/assign"
payload := strings.NewReader("{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.isnap.ai/v1/lines/assign")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.isnap.ai/v1/lines/assign")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"area_code\": \"<string>\",\n \"inbound_only\": true,\n \"as_test_line\": true,\n \"metadata\": {\n \"crm_account_id\": \"acc_123\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"id": "<string>",
"phone_number": "<string>",
"area_code": "<string>",
"country_code": "<string>",
"state": "<string>",
"state_name": "<string>",
"billing_tier": "rental_iphone",
"byod": true,
"inbound_only": true,
"status": "<string>",
"monthly_price": 1,
"stripe_subscription_id": "<string>",
"activated_at": "<string>",
"expires_at": "<string>",
"anniversary_at": "<string>",
"cancel_at": "<string>",
"billing_anchor_at": "<string>",
"next_anchor_at": "<string>",
"pending_variant": {
"inbound_only": true,
"effective_at": "<string>"
},
"created_at": "<string>",
"metadata": {},
"test_line": true,
"shared": true,
"capabilities": "<unknown>",
"fulfillment_status": "<string>"
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}{
"success": false,
"data": "<unknown>",
"error": {
"status": 123,
"code": "<string>",
"message": "<string>",
"retry_after": 123,
"retry_at": "<string>",
"issues": [
{
"path": [
"<string>"
],
"message": "<string>",
"code": "<string>",
"min": 123,
"max": 123
}
]
},
"trace_id": "<string>",
"request_id": "<string>"
}- Credential: an API key with no list of lines. See Assignment.
- Account: wholesale partners only: any other account receives
402 checkout_required. - Line-scoped keys: every line-scoped key gets
403 forbidden. - Test keys: an assignment sent with an
isnap_test_account key takes a real line, billed like any other: see Test keys. Idempotency-Key: honored, and remembered for 24 hours. Without it, every retry takes one more billable line. See Retries and Lines and hosted macOS sessions.- Events: none. See Events.
Errors
| Status | error.code | When |
|---|---|---|
| 400 | validation_failed | The Idempotency-Key is longer than 255 characters, or the body is invalid. |
| 400 | reserved_metadata_key | metadata names migration_ref or proof_line. |
| 400 | inbound_only_not_rental | inbound_only is true with a BYOD kind. |
| 400 | test_line_not_rental | as_test_line is true with a BYOD kind. |
| 400 | test_line_not_inbound_only | as_test_line and inbound_only are both true. |
| 402 | checkout_required | Your account is not a wholesale partner. This is checked after the body passes validation, before the other rules of this operation on the body, and before any line is looked at. |
| 403 | forbidden | The request uses a line-scoped key. |
| 409 | no_matching_line | No available line matches, or the line that was picked failed its last checks. |
| 409 | line_on_rented_macos_session, line_takes_no_macos_session | The hosted macOS session of the line that was picked does not fit. |
| 409 | idempotency_key_collision | The same Idempotency-Key was sent with another body. |
| 503 | idempotency_in_flight | A request with the same Idempotency-Key is still running. Retry with the same key. |
as_test_line: true, the call can also return an error of convert-to-test after the line was assigned. The line then stays yours as a rented line: see Assignment.
The errors that every operation shares are in Errors.Authorizations
An API key created in the iSnap dashboard, or a trial key, sent as Authorization: Bearer <key>. An API key starts with isnap_live_ or isnap_test_; both act on the same account, lines and billing. A trial key acts on its trial only.
Headers
Optional key that makes a retry safe. A request repeated with the same key, by the same API key, with the same method, path and body, within 24 hours, returns the first successful response unchanged, its trace_id and request_id included, and does not act again. The body is compared byte for byte: a request with no body and a request with {} are two different requests. The same key with another method, path or body returns 409 idempotency_key_collision. While the first request is still running, a retry returns 503 idempotency_in_flight; a request that never completes frees its key after 60 seconds. Only a 2xx response is recorded: after a failed request, the retry runs again. At most 255 characters: a longer key returns 400 validation_failed. The X-Idempotency-Key header is read when Idempotency-Key is absent.
255Body
The line to take: its kind and, optionally, its area code, its variant and its metadata.
The kind of line to take.
rental_iphone, rental_android, byod_imessage, byod_android Take a line whose area_code is exactly this value. Omit it to take a line of any area code.
1 - 10true to take the line as an inbound-only line. Rented tiers only (400 inbound_only_not_rental otherwise). Defaults to false: a two-way line.
true to make the line a test line for the trials of your own prospects, in the same call. Rented tiers only (400 test_line_not_rental otherwise), and not together with inbound_only (400 test_line_not_inbound_only). Defaults to false.
Your own key-value data, set on the line in place of any metadata it carried. Omit it to clear the metadata of the line. At most 20 keys and 8,192 bytes once serialized as JSON. The keys migration_ref and proof_line are reserved (400 reserved_metadata_key). Never put personal data or secrets in it.
Show child attributes
Show child attributes
{ "crm_account_id": "acc_123" }
Response
The assigned line, active, with its full phone number.
Always true on a success response.
true A line. billing_tier, byod, shared, test_line and inbound_only tell the kinds of line apart: a rented line (two-way or inbound-only), a BYOD line, a shared line, a test line.
Show child attributes
Show child attributes
Trace id of the request that produced this response: 32 lowercase hexadecimal characters. Quote it when you report a problem to iSnap.
Id of the request that produced this response: req_ followed by 25 letters or digits.