# Requires: npm i -g @infinite_dev/cli && export INFINITE_API_KEY=sk_sandbox_...
# Escape hatch for any endpoint: infinite api <METHOD> <path>
infinite api POST /v1/customers/cus_abc123/verification/individual \
--body '<request-json>'Save individual customer verification (cus_abc123).
# Infinite MCP is read-only for this endpoint — use a dedicated MCP tool when one exists, otherwise run the CLI tab.import requests
url = "https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual"
payload = {
"metadata": {
"source": "mobile_app",
"referrer": "partner_xyz"
},
"hasAgreedToTos": True,
"firstName": "John",
"middleName": "Michael",
"nickname": "Johnny",
"lastName": "Doe",
"transliteratedFirstName": "Zhang",
"transliteratedMiddleName": "<string>",
"transliteratedLastName": "San",
"email": "john.doe@example.com",
"phone": "+14155551234",
"dateOfBirth": "1990-01-15",
"nationality": "US",
"taxResidenceCountry": "GB",
"taxIdentificationNumber": "123-45-6789",
"occupation": "151252",
"requestedCapabilities": [],
"accountPurposeExplanation": "<string>",
"sourceOfFundsDescription": "<string>",
"expectedMonthlyPaymentsUsd": 5000,
"actingAsIntermediary": False,
"supportingDocuments": [
{
"file": "doc_abc123",
"requirementId": "<string>",
"type": "PROOF_OF_ADDRESS",
"subtype": "UTILITY_BILL",
"description": "Passport issued in 2020",
"remarks": "Uploaded to support proof of business address"
}
],
"proofOfSourceOfFunds": [
{
"file": "doc_abc123",
"requirementId": "<string>",
"type": "PROOF_OF_ADDRESS",
"subtype": "UTILITY_BILL",
"description": "Passport issued in 2020",
"remarks": "Uploaded to support proof of business address"
}
],
"signedAgreementId": "tos_abc123",
"ipAddress": "192.168.1.1"
}
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({
metadata: {source: 'mobile_app', referrer: 'partner_xyz'},
hasAgreedToTos: true,
firstName: 'John',
middleName: 'Michael',
nickname: 'Johnny',
lastName: 'Doe',
transliteratedFirstName: 'Zhang',
transliteratedMiddleName: '<string>',
transliteratedLastName: 'San',
email: 'john.doe@example.com',
phone: '+14155551234',
dateOfBirth: '1990-01-15',
nationality: 'US',
taxResidenceCountry: 'GB',
taxIdentificationNumber: '123-45-6789',
occupation: '151252',
requestedCapabilities: [],
accountPurposeExplanation: '<string>',
sourceOfFundsDescription: '<string>',
expectedMonthlyPaymentsUsd: 5000,
actingAsIntermediary: false,
supportingDocuments: [
{
file: 'doc_abc123',
requirementId: '<string>',
type: 'PROOF_OF_ADDRESS',
subtype: 'UTILITY_BILL',
description: 'Passport issued in 2020',
remarks: 'Uploaded to support proof of business address'
}
],
proofOfSourceOfFunds: [
{
file: 'doc_abc123',
requirementId: '<string>',
type: 'PROOF_OF_ADDRESS',
subtype: 'UTILITY_BILL',
description: 'Passport issued in 2020',
remarks: 'Uploaded to support proof of business address'
}
],
signedAgreementId: 'tos_abc123',
ipAddress: '192.168.1.1'
})
};
fetch('https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual', 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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual",
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([
'metadata' => [
'source' => 'mobile_app',
'referrer' => 'partner_xyz'
],
'hasAgreedToTos' => true,
'firstName' => 'John',
'middleName' => 'Michael',
'nickname' => 'Johnny',
'lastName' => 'Doe',
'transliteratedFirstName' => 'Zhang',
'transliteratedMiddleName' => '<string>',
'transliteratedLastName' => 'San',
'email' => 'john.doe@example.com',
'phone' => '+14155551234',
'dateOfBirth' => '1990-01-15',
'nationality' => 'US',
'taxResidenceCountry' => 'GB',
'taxIdentificationNumber' => '123-45-6789',
'occupation' => '151252',
'requestedCapabilities' => [
],
'accountPurposeExplanation' => '<string>',
'sourceOfFundsDescription' => '<string>',
'expectedMonthlyPaymentsUsd' => 5000,
'actingAsIntermediary' => false,
'supportingDocuments' => [
[
'file' => 'doc_abc123',
'requirementId' => '<string>',
'type' => 'PROOF_OF_ADDRESS',
'subtype' => 'UTILITY_BILL',
'description' => 'Passport issued in 2020',
'remarks' => 'Uploaded to support proof of business address'
]
],
'proofOfSourceOfFunds' => [
[
'file' => 'doc_abc123',
'requirementId' => '<string>',
'type' => 'PROOF_OF_ADDRESS',
'subtype' => 'UTILITY_BILL',
'description' => 'Passport issued in 2020',
'remarks' => 'Uploaded to support proof of business address'
]
],
'signedAgreementId' => 'tos_abc123',
'ipAddress' => '192.168.1.1'
]),
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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual"
payload := strings.NewReader("{\n \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual")
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 \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\n}"
response = http.request(request)
puts response.read_body{
"customerId": "cus_abc123",
"status": "DRAFT",
"documentIds": [
"doc_abc123",
"doc_xyz789"
],
"submittedAt": "2026-09-15T10:30:00Z",
"missingRequirements": [
{
"requirementType": "FIELD",
"key": "metadata.infiniteTosAcceptanceId",
"displayName": "Infinite Terms of Service & Privacy Policy"
},
{
"requirementType": "DOCUMENT",
"key": "identity.government_id_front",
"displayName": "Government ID"
}
],
"reviewWarnings": [
"businessData.businessAddressProof[0] failed AI proof-of-address validation (confidence 0.62): The address appears similar but the issue date is unclear."
]
}Save individual customer verification
Save complete individual verification data for an INDIVIDUAL customer.
Key features:
- Submit comprehensive individual verification data
- Reference previously uploaded identity and supporting documents via document IDs (doc_xxx)
- Optionally submit the customer for review in the same request via
?submit=true
Data model covers the individual verification payload:
- Personal info, address, employment, tax ID, government ID, supporting docs
Document workflow:
- Upload documents using POST /documents (with customerId in body)
- Confirm each document using POST /documents/:id/confirm
- Save the complete verification data to this endpoint using document references (doc_xxx)
Required for all files:
- Create a minimal customer record first using POST /customers/individuals with basic info (name, email, country code)
- Upload documents using POST /documents (with customerId in body) and POST /documents/:id/confirm
- Save the complete verification data to this endpoint using document references (doc_xxx)
# Requires: npm i -g @infinite_dev/cli && export INFINITE_API_KEY=sk_sandbox_...
# Escape hatch for any endpoint: infinite api <METHOD> <path>
infinite api POST /v1/customers/cus_abc123/verification/individual \
--body '<request-json>'Save individual customer verification (cus_abc123).
# Infinite MCP is read-only for this endpoint — use a dedicated MCP tool when one exists, otherwise run the CLI tab.import requests
url = "https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual"
payload = {
"metadata": {
"source": "mobile_app",
"referrer": "partner_xyz"
},
"hasAgreedToTos": True,
"firstName": "John",
"middleName": "Michael",
"nickname": "Johnny",
"lastName": "Doe",
"transliteratedFirstName": "Zhang",
"transliteratedMiddleName": "<string>",
"transliteratedLastName": "San",
"email": "john.doe@example.com",
"phone": "+14155551234",
"dateOfBirth": "1990-01-15",
"nationality": "US",
"taxResidenceCountry": "GB",
"taxIdentificationNumber": "123-45-6789",
"occupation": "151252",
"requestedCapabilities": [],
"accountPurposeExplanation": "<string>",
"sourceOfFundsDescription": "<string>",
"expectedMonthlyPaymentsUsd": 5000,
"actingAsIntermediary": False,
"supportingDocuments": [
{
"file": "doc_abc123",
"requirementId": "<string>",
"type": "PROOF_OF_ADDRESS",
"subtype": "UTILITY_BILL",
"description": "Passport issued in 2020",
"remarks": "Uploaded to support proof of business address"
}
],
"proofOfSourceOfFunds": [
{
"file": "doc_abc123",
"requirementId": "<string>",
"type": "PROOF_OF_ADDRESS",
"subtype": "UTILITY_BILL",
"description": "Passport issued in 2020",
"remarks": "Uploaded to support proof of business address"
}
],
"signedAgreementId": "tos_abc123",
"ipAddress": "192.168.1.1"
}
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({
metadata: {source: 'mobile_app', referrer: 'partner_xyz'},
hasAgreedToTos: true,
firstName: 'John',
middleName: 'Michael',
nickname: 'Johnny',
lastName: 'Doe',
transliteratedFirstName: 'Zhang',
transliteratedMiddleName: '<string>',
transliteratedLastName: 'San',
email: 'john.doe@example.com',
phone: '+14155551234',
dateOfBirth: '1990-01-15',
nationality: 'US',
taxResidenceCountry: 'GB',
taxIdentificationNumber: '123-45-6789',
occupation: '151252',
requestedCapabilities: [],
accountPurposeExplanation: '<string>',
sourceOfFundsDescription: '<string>',
expectedMonthlyPaymentsUsd: 5000,
actingAsIntermediary: false,
supportingDocuments: [
{
file: 'doc_abc123',
requirementId: '<string>',
type: 'PROOF_OF_ADDRESS',
subtype: 'UTILITY_BILL',
description: 'Passport issued in 2020',
remarks: 'Uploaded to support proof of business address'
}
],
proofOfSourceOfFunds: [
{
file: 'doc_abc123',
requirementId: '<string>',
type: 'PROOF_OF_ADDRESS',
subtype: 'UTILITY_BILL',
description: 'Passport issued in 2020',
remarks: 'Uploaded to support proof of business address'
}
],
signedAgreementId: 'tos_abc123',
ipAddress: '192.168.1.1'
})
};
fetch('https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual', 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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual",
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([
'metadata' => [
'source' => 'mobile_app',
'referrer' => 'partner_xyz'
],
'hasAgreedToTos' => true,
'firstName' => 'John',
'middleName' => 'Michael',
'nickname' => 'Johnny',
'lastName' => 'Doe',
'transliteratedFirstName' => 'Zhang',
'transliteratedMiddleName' => '<string>',
'transliteratedLastName' => 'San',
'email' => 'john.doe@example.com',
'phone' => '+14155551234',
'dateOfBirth' => '1990-01-15',
'nationality' => 'US',
'taxResidenceCountry' => 'GB',
'taxIdentificationNumber' => '123-45-6789',
'occupation' => '151252',
'requestedCapabilities' => [
],
'accountPurposeExplanation' => '<string>',
'sourceOfFundsDescription' => '<string>',
'expectedMonthlyPaymentsUsd' => 5000,
'actingAsIntermediary' => false,
'supportingDocuments' => [
[
'file' => 'doc_abc123',
'requirementId' => '<string>',
'type' => 'PROOF_OF_ADDRESS',
'subtype' => 'UTILITY_BILL',
'description' => 'Passport issued in 2020',
'remarks' => 'Uploaded to support proof of business address'
]
],
'proofOfSourceOfFunds' => [
[
'file' => 'doc_abc123',
'requirementId' => '<string>',
'type' => 'PROOF_OF_ADDRESS',
'subtype' => 'UTILITY_BILL',
'description' => 'Passport issued in 2020',
'remarks' => 'Uploaded to support proof of business address'
]
],
'signedAgreementId' => 'tos_abc123',
'ipAddress' => '192.168.1.1'
]),
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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual"
payload := strings.NewReader("{\n \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\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://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sandbox.api.infinite.dev/v1/customers/{id}/verification/individual")
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 \"metadata\": {\n \"source\": \"mobile_app\",\n \"referrer\": \"partner_xyz\"\n },\n \"hasAgreedToTos\": true,\n \"firstName\": \"John\",\n \"middleName\": \"Michael\",\n \"nickname\": \"Johnny\",\n \"lastName\": \"Doe\",\n \"transliteratedFirstName\": \"Zhang\",\n \"transliteratedMiddleName\": \"<string>\",\n \"transliteratedLastName\": \"San\",\n \"email\": \"john.doe@example.com\",\n \"phone\": \"+14155551234\",\n \"dateOfBirth\": \"1990-01-15\",\n \"nationality\": \"US\",\n \"taxResidenceCountry\": \"GB\",\n \"taxIdentificationNumber\": \"123-45-6789\",\n \"occupation\": \"151252\",\n \"requestedCapabilities\": [],\n \"accountPurposeExplanation\": \"<string>\",\n \"sourceOfFundsDescription\": \"<string>\",\n \"expectedMonthlyPaymentsUsd\": 5000,\n \"actingAsIntermediary\": false,\n \"supportingDocuments\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"proofOfSourceOfFunds\": [\n {\n \"file\": \"doc_abc123\",\n \"requirementId\": \"<string>\",\n \"type\": \"PROOF_OF_ADDRESS\",\n \"subtype\": \"UTILITY_BILL\",\n \"description\": \"Passport issued in 2020\",\n \"remarks\": \"Uploaded to support proof of business address\"\n }\n ],\n \"signedAgreementId\": \"tos_abc123\",\n \"ipAddress\": \"192.168.1.1\"\n}"
response = http.request(request)
puts response.read_body{
"customerId": "cus_abc123",
"status": "DRAFT",
"documentIds": [
"doc_abc123",
"doc_xyz789"
],
"submittedAt": "2026-09-15T10:30:00Z",
"missingRequirements": [
{
"requirementType": "FIELD",
"key": "metadata.infiniteTosAcceptanceId",
"displayName": "Infinite Terms of Service & Privacy Policy"
},
{
"requirementType": "DOCUMENT",
"key": "identity.government_id_front",
"displayName": "Government ID"
}
],
"reviewWarnings": [
"businessData.businessAddressProof[0] failed AI proof-of-address validation (confidence 0.62): The address appears similar but the issue date is unclear."
]
}Required at submit
Every field on this endpoint is optional so you can save progress. Passingsubmit=true, or calling POST /customers/{id}/submit, requires the base individual package: first and last name, email, phone, date of birth, tax identification number, residential address, government ID, and a selfie. Proof of address is required when the customer does not reside in the US. Terms acceptance is also required.
The authoritative checklist for a customer is GET /customers//compliance. Enhanced diligence is not part of that base gate. When it applies, it is collected after submit.Authorizations
API Key in Bearer format (e.g., Bearer sk_test_...)
Headers
API key
Path Parameters
Customer ID
"cus_abc123"
Query Parameters
If true, submit the customer for review after saving verification data.
true
Body
Additional metadata
{
"source": "mobile_app",
"referrer": "partner_xyz"
}
Set to true to indicate the customer has agreed to the Terms of Service and Privacy Policy. When true, a TOS acceptance record will be automatically created. This is a convenience for API-based integrations - alternatively, you can use the /v1/tos endpoints to create a TOS acceptance record and pass the ID in metadata.infiniteTosAcceptanceId.
true
First name
"John"
Middle name
"Michael"
Nickname
"Johnny"
Last name
"Doe"
Transliterated first name (required if firstName has non-Latin-1 chars)
"Zhang"
Transliterated middle name (required if middleName has non-Latin-1 chars)
Transliterated last name (required if lastName has non-Latin-1 chars)
"San"
Email address
"john.doe@example.com"
Phone number in E.164 format
"+14155551234"
Date of birth (YYYY-MM-DD)
"1990-01-15"
Current residential address. Use the nested transliterated field for Latin character versions of non-Latin addresses.
Show child attributes
Show child attributes
Nationality (ISO 3166-2)
"US"
Optional. Country of tax residence (ISO 3166-1 alpha-2). Provide only when it differs from nationality; tax ID format validation falls back to nationality when omitted.
"GB"
Tax/identity number (e.g., SSN in US, NINO in UK). This is the number only - for physical ID documents (passport, driver's license, state ID), use the governmentId field.
Validated against country-specific formats when nationality is provided. Accepts NOT_APPLICABLE when no tax ID is available, except for US nationals, who must provide a real SSN/ITIN. If the value does not match the expected format, prefix with OVERRIDE: (e.g. OVERRIDE:123-45-6789) to store it as-is. These should be used sparingly — missing or overridden tax IDs may trigger additional customer due diligence.
"123-45-6789"
Current occupation as an occupation code
"151252"
Employment status
EMPLOYED, SELF_EMPLOYED, UNEMPLOYED, STUDENT, RETIRED, HOMEMAKER Purpose of account
PERSONAL_EXPENSES, BUSINESS_OPERATIONS, INVESTMENT, SAVINGS, OTHER Capabilities requested by the customer
USD_ACH_PAYIN, USD_ACH_PAYOUT, USD_WIRE_PAYIN, USD_WIRE_PAYOUT, USD_BALANCE, USD_YIELD, SWIFT_PAYIN, SWIFT_PAYOUT, STABLECOIN_PAYIN, STABLECOIN_PAYOUT, STABLECOIN_SWAPS, AED_FX_PAYOUT, AUD_FX_PAYOUT, BHD_FX_PAYOUT, BOB_FX_PAYOUT, BRL_FX_PAYOUT, CLP_FX_PAYOUT, CNY_FX_PAYOUT, COP_FX_PAYOUT, DOP_FX_PAYOUT, EGP_FX_PAYOUT, EUR_FX_PAYOUT, GBP_FX_PAYOUT, HKD_FX_PAYOUT, IDR_FX_PAYOUT, INR_FX_PAYOUT, JPY_FX_PAYOUT, KRW_FX_PAYOUT, KWD_FX_PAYOUT, MXN_FX_PAYOUT, MYR_FX_PAYOUT, PEN_FX_PAYOUT, PHP_FX_PAYOUT, PYG_FX_PAYOUT, QAR_FX_PAYOUT, SAR_FX_PAYOUT, SGD_FX_PAYOUT, THB_FX_PAYOUT, TRY_FX_PAYOUT, TWD_FX_PAYOUT, USD_FX_PAYOUT, VND_FX_PAYOUT Account purpose explanation (required if purpose is other)
Source of funds
COMPANY_FUNDS, ECOMMERCE_RESELLER, GAMBLING_PROCEEDS, GIFTS, GOVERNMENT_BENEFITS, INHERITANCE, INVESTMENTS_LOANS, PENSION_RETIREMENT, SALARY, SALE_OF_ASSETS_REAL_ESTATE, SAVINGS, SOMEONE_ELSES_FUNDS Source of funds description
Expected monthly payment volume in USD
5000
Acting as intermediary for others
false
Physical government-issued ID document (e.g., passport, driver's license, state ID). Includes document type, ID number, and front/back images. For tax/identity numbers like SSN, use taxIdentificationNumber instead.
Show child attributes
Show child attributes
Proof of address document. Required for individual customers residing outside the US. Acceptable documents: utility bill, bank statement, lease agreement, or government letter dated within the last 90 days.
Show child attributes
Show child attributes
Supporting documents
Show child attributes
Show child attributes
Proof of source of funds documents for individual EDD flows.
Show child attributes
Show child attributes
Signed terms of service agreement ID. Use POST /v1/tos/generate to create a TOS agreement and obtain the ID. See Terms of Service documentation for details.
"tos_abc123"
Client IP address for fraud detection
"192.168.1.1"
Response
Verification submitted successfully
Customer ID
"cus_abc123"
Customer status after saving verification data
"DRAFT"
Document IDs uploaded
["doc_abc123", "doc_xyz789"]
Submission timestamp when the customer has actually been submitted for review.
"2026-09-15T10:30:00Z"
Merged list of missing fields and documents for full verification (data is saved but customer remains in DRAFT)
Show child attributes
Show child attributes
[
{
"requirementType": "FIELD",
"key": "metadata.infiniteTosAcceptanceId",
"displayName": "Infinite Terms of Service & Privacy Policy"
},
{
"requirementType": "DOCUMENT",
"key": "identity.government_id_front",
"displayName": "Government ID"
}
]
Document validation warnings that did not block submission and should be manually reviewed.
[
"businessData.businessAddressProof[0] failed AI proof-of-address validation (confidence 0.62): The address appears similar but the issue date is unclear."
]
Was this page helpful?