# Submit a toll-free verification for review

Source: https://jointextkit.com/docs/api/toll-free-verifications/submit
Index: https://jointextkit.com/llms.txt

`POST /v1/toll-free-verifications/{id}/submit`

Sends a draft, or a rejected form you fixed, to our team: it comes back `in_review`. A person on our team checks every form by hand, usually within a business day, then sends it to the carriers (status `submitted`; usually days, sometimes weeks). Nothing goes to the carriers straight from this call. The first submit for a business also carries the signed business attestation; without one on file it answers 400 attestation_required (param attestation). Later forms for the same business details need none. While anything the carriers require is missing it answers 409 invalid_state with `problems`. Toll-free verification has no fee.

Send your API key as a bearer token: `Authorization: Bearer ssms_sk_...`. Test keys run this endpoint against the [sandbox](/docs/sandbox); see [Authentication](/docs/authentication) for key modes and scopes.

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Example: `tfv_a1B2c3D4e5F6`. |

## Request body

JSON (`Content-Type: application/json`). The body is optional.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `attestation` | BusinessAttestation | No | Signed by someone authorized to act for the business, once per business: that they are authorized, that the details match the business's IRS records, and that the business will text only people who agreed to it and will follow the Messaging Policy. Kept as signed, with the exact wording, who sent it (the API key), the IP address, the user agent and the date of our legal documents. |

## Responses

| Status | Meaning | Body |
| --- | --- | --- |
| 200 | Toll-free verification, status in_review | `TollFreeVerification` |
| 400 | invalid_request: a missing business detail or attestation field; attestation_required: the business has no signature on file for these details | `Error` |
| 401 | Missing, malformed, or revoked API key | `Error` |
| 402 | Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or charged | `Error` |
| 404 | Not found | `Error` |
| 409 | invalid_state: already in review or further along, or not complete (problems lists every missing answer) | `Error` |
| 429 | Rate limit or quota exceeded | `Error` |

### 200: `TollFreeVerification` fields

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Example: `tfv_a1B2c3D4e5F6`. |
| `object` | `toll_free_verification` |  |
| `status` | `draft`, `in_review`, `submitted`, `verified`, `rejected` | draft: not submitted. in_review: our team is checking it by hand; nothing has gone to the carriers yet. submitted: we sent it to the carriers; waiting on their answer. verified: its numbers text anyone who opted in. rejected: sent back; rejection.reason says why. |
| `numbers` | array of string |  |
| `business_name` | string |  |
| `ready` | boolean | Nothing the carriers require is missing (problems is empty). |
| `problems` | array of object | What the carriers would send it back for, one entry per answer to fix. |
| `problems[].field` | string | Example: `ein`. |
| `problems[].message` | string |  |
| `editable` | boolean | Whether PATCH may change it now (draft, in_review and rejected). |
| `next_actor` | `you`, `textkit`, `carriers`, `nobody` | Who acts next. |
| `form` | TollFreeVerificationInput | The form as it stands, every field. contact_email is always our support address: the carriers write to us, and we forward what only you can answer. |
| `business` | object | The business on the form, as business verification sees it. Nullable. |
| `business.status` | `not_started`, `pending`, `verified`, `rejected` |  |
| `business.attestation_needed` | boolean | Submit needs an attestation for these business details. |
| `business.signed` | object | Nullable. |
| `business.signed.signer_name` | string |  |
| `business.signed.signer_title` | string |  |
| `business.signed.signed_at` | string (date-time) |  |
| `business.rejection` | object | Nullable. |
| `business.rejection.code` | string |  |
| `business.rejection.note` | string | Nullable. |
| `rejection` | object | Set while rejected: what the carriers or our team asked for. Nullable. |
| `rejection.reason` | string |  |
| `rejection.rejected_at` | string (date-time) |  |
| `carrier_reference` | string | The carriers' case number, once they give one. Nullable. |
| `registration_id` | string | The registration it was filled in from, if any. Nullable. |
| `history` | array of object |  |
| `history[].at` | string (date-time) |  |
| `history[].status` | `draft`, `in_review`, `submitted`, `verified`, `rejected` |  |
| `history[].actor` | `customer`, `staff`, `system`, `carrier` |  |
| `history[].note` | string | Nullable. |
| `created_at` | string (date-time) |  |
| `updated_at` | string (date-time) |  |

## Errors

| Status | When |
| --- | --- |
| 400 | invalid_request: a missing business detail or attestation field; attestation_required: the business has no signature on file for these details |
| 401 | Missing, malformed, or revoked API key |
| 402 | Billable live calls only: the prepaid credit balance cannot cover the call (insufficient_credits); nothing was done or charged |
| 404 | Not found |
| 409 | invalid_state: already in review or further along, or not complete (problems lists every missing answer) |
| 429 | Rate limit or quota exceeded |

Every error has the same JSON shape, and `request_id` matches the `X-Request-Id` response header. [Errors](/docs/errors) lists every code and what to do about it.

```json
{
  "error": {
    "code": "invalid_request",
    "message": "What went wrong, in plain words.",
    "param": "the_field",
    "request_id": "req_a1B2c3D4e5F6g7H8"
  }
}
```

## Examples

### Node.js

The Node.js SDK does not wrap this endpoint yet; call it over HTTP.

```javascript
const res = await fetch('https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TEXTKIT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({}),
});

if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
```

### PHP

```php
<?php

$ch = curl_init('https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('TEXTKIT_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode((object) []),
]);

$data = json_decode(curl_exec($ch), true);
```

### Python

The Python SDK does not wrap this endpoint yet; call it over HTTP.

```python
import json, os, urllib.request

req = urllib.request.Request(
    "https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit",
    method="POST",
    headers={
        "Authorization": f"Bearer {os.environ['TEXTKIT_API_KEY']}",
        "Content-Type": "application/json",
    },
    data=json.dumps({}).encode(),
)
with urllib.request.urlopen(req) as res:
    data = json.load(res)
```

### Ruby

```ruby
require "net/http"
require "json"

uri = URI("https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV["TEXTKIT_API_KEY"]}"
req["Content-Type"] = "application/json"
req.body = {}.to_json

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
```

### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("POST", "https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit", body)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("TEXTKIT_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	data, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(data))
}
```

### Rust

```rust
// cargo add reqwest --features blocking,json
// cargo add serde_json
use serde_json::json;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("TEXTKIT_API_KEY")?;
    let res = reqwest::blocking::Client::new()
        .post("https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit")
        .bearer_auth(key)
        .json(&json!({}))
        .send()?
        .error_for_status()?;
    let data: serde_json::Value = res.json()?;
    println!("{data}");
    Ok(())
}
```

### Java

```java
import java.net.URI;
import java.net.http.*;

public class Main {
    public static void main(String[] args) throws Exception {
        var request = HttpRequest.newBuilder(URI.create("https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit"))
            .header("Authorization", "Bearer " + System.getenv("TEXTKIT_API_KEY"))
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString("""
                {}
                """))
            .build();

        var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode() + " " + response.body());
    }
}
```

### .NET

```csharp
using System.Net.Http.Headers;
using System.Text;

var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("TEXTKIT_API_KEY"));

var body = new StringContent("""
    {}
    """, Encoding.UTF8, "application/json");
var res = await http.PostAsync("https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit", body);
res.EnsureSuccessStatusCode();

var data = await res.Content.ReadAsStringAsync();
```

### cURL

```bash
curl -X POST "https://api.jointextkit.com/v1/toll-free-verifications/tfv_a1B2c3D4e5F6/submit" \
  -H "Authorization: Bearer $TEXTKIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

## Related

- Guide: [Numbers](/docs/numbers)
- [All toll-free verifications endpoints](/docs/api#toll-free-verifications)
- [API reference](/docs/api)
