curl --request POST \
--url https://app.instantcompliance.ai/api/v1/customers/{id}/kyc \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"method": "automated"
}
'import requests
url = "https://app.instantcompliance.ai/api/v1/customers/{id}/kyc"
payload = { "method": "automated" }
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({method: 'automated'})
};
fetch('https://app.instantcompliance.ai/api/v1/customers/{id}/kyc', 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://app.instantcompliance.ai/api/v1/customers/{id}/kyc",
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([
'method' => 'automated'
]),
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://app.instantcompliance.ai/api/v1/customers/{id}/kyc"
payload := strings.NewReader("{\n \"method\": \"automated\"\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://app.instantcompliance.ai/api/v1/customers/{id}/kyc")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"method\": \"automated\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.instantcompliance.ai/api/v1/customers/{id}/kyc")
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 \"method\": \"automated\"\n}"
response = http.request(request)
puts response.read_body{
"id": "550e8400-e29b-41d4-a716-446655440000",
"external_id": "crm-7741",
"type": "INDIVIDUAL",
"full_name": "Jane Doe",
"email": "jane@example.com",
"kyc_status": "VERIFIED",
"kyc_started_at": "2026-06-23T01:00:00Z",
"kyc_completed_at": "2026-06-23T01:12:00Z",
"identity": {
"verified_legal_name": "JANE DOE",
"verified_country": "AUS"
},
"aml": {
"status": "CLEAR",
"screened_at": "2026-06-23T01:12:00Z",
"last_reviewed_at": null,
"flags": {
"pep": false,
"sanctions": false,
"adverse_media": false,
"terrorism": false
}
},
"added_via": "INTEGRATION",
"created_at": "2026-06-22T22:14:00Z",
"updated_at": "2026-06-23T01:12:05Z"
}{
"error": {
"code": "unauthorized",
"message": "Invalid or revoked API key."
}
}{
"error": {
"code": "insufficient_credits",
"message": "Insufficient credits to start this verification."
}
}{
"error": {
"code": "forbidden_scope",
"message": "This API key does not have the required scope. customers:write",
"details": {
"required_scope": "customers:write"
}
}
}{
"error": {
"code": "not_found",
"message": "Customer not found."
}
}{
"error": {
"code": "conflict",
"message": "KYB verification has already been started for this customer."
}
}{
"error": {
"code": "validation_failed",
"message": "Invalid customer payload.",
"details": {
"issues": {
"email": [
"Must be a valid email address."
]
}
}
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Slow down and retry shortly.",
"details": {
"limit": 60,
"window_seconds": 60
}
}
}Start a customer's KYC
Start identity verification (KYC) for an individual — the same flow the in-app “Start verification” runs. This spends credits (or bills the customer), unlike ingest.
automated(default) emails the customer a secure verification link and charges one KYC check to the organisation’s credits.manualarms the record for an officer to upload documents in the app; it does not charge.
Payer follows the customer record’s billing default unless payer
overrides it. When the customer pays, the check arms payment-pending
and the pay link is emailed — the customer pays by card at the portal;
no card is handled at API-call time.
Requires the verification:write scope. Include an Idempotency-Key
header to make retries safe for 24 hours.
curl --request POST \
--url https://app.instantcompliance.ai/api/v1/customers/{id}/kyc \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"method": "automated"
}
'import requests
url = "https://app.instantcompliance.ai/api/v1/customers/{id}/kyc"
payload = { "method": "automated" }
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({method: 'automated'})
};
fetch('https://app.instantcompliance.ai/api/v1/customers/{id}/kyc', 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://app.instantcompliance.ai/api/v1/customers/{id}/kyc",
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([
'method' => 'automated'
]),
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://app.instantcompliance.ai/api/v1/customers/{id}/kyc"
payload := strings.NewReader("{\n \"method\": \"automated\"\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://app.instantcompliance.ai/api/v1/customers/{id}/kyc")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"method\": \"automated\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.instantcompliance.ai/api/v1/customers/{id}/kyc")
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 \"method\": \"automated\"\n}"
response = http.request(request)
puts response.read_body{
"id": "550e8400-e29b-41d4-a716-446655440000",
"external_id": "crm-7741",
"type": "INDIVIDUAL",
"full_name": "Jane Doe",
"email": "jane@example.com",
"kyc_status": "VERIFIED",
"kyc_started_at": "2026-06-23T01:00:00Z",
"kyc_completed_at": "2026-06-23T01:12:00Z",
"identity": {
"verified_legal_name": "JANE DOE",
"verified_country": "AUS"
},
"aml": {
"status": "CLEAR",
"screened_at": "2026-06-23T01:12:00Z",
"last_reviewed_at": null,
"flags": {
"pep": false,
"sanctions": false,
"adverse_media": false,
"terrorism": false
}
},
"added_via": "INTEGRATION",
"created_at": "2026-06-22T22:14:00Z",
"updated_at": "2026-06-23T01:12:05Z"
}{
"error": {
"code": "unauthorized",
"message": "Invalid or revoked API key."
}
}{
"error": {
"code": "insufficient_credits",
"message": "Insufficient credits to start this verification."
}
}{
"error": {
"code": "forbidden_scope",
"message": "This API key does not have the required scope. customers:write",
"details": {
"required_scope": "customers:write"
}
}
}{
"error": {
"code": "not_found",
"message": "Customer not found."
}
}{
"error": {
"code": "conflict",
"message": "KYB verification has already been started for this customer."
}
}{
"error": {
"code": "validation_failed",
"message": "Invalid customer payload.",
"details": {
"issues": {
"email": [
"Must be a valid email address."
]
}
}
}
}{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Slow down and retry shortly.",
"details": {
"limit": 60,
"window_seconds": 60
}
}
}verification:write
scope.
Lanes
automated(default) — emails the customer a secure verification link and charges one KYC check to your organisation’s credits. The shareable link is also returned asverification_link.manual— arms the record for an officer to upload documents inside Instant Compliance. Does not charge.
Who pays
payer is optional. Omit it to honour the customer record’s own billing
default (set by your org’s billing settings). Set payer: customer to
bill the end customer: the check arms payment-pending and the pay link
is emailed — the customer pays by card at the portal. No card is handled
at API-call time.
Errors worth handling
402 insufficient_credits— your org has no credits and the check is org-paid. Nothing is armed and nothing is charged; top up (or start it customer-paid) and retry.409 conflict— a verification has already been started for this customer.422 validation_failed— a precondition is missing (e.g. an automated start on a customer with no email).
Idempotency-Key header so a retried start is not run twice.Authorizations
Bearer API key issued from Settings → Developers in your
Instant Compliance organisation. Format: ic_live_….
Headers
Caller-supplied unique key for safe retries. Repeat the same key within 24 hours and we replay the original response instead of repeating the side effect. Reusing the key with a different request body returns 409 idempotency_conflict.
255Path Parameters
Customer identifier. Accepts either Instant Compliance's UUID or your
own external_id.
Body
Options for starting a customer's KYC. All fields optional.
automated emails the customer a link and charges; manual arms
for officer document upload and does not charge.
automated, manual Who pays for the check. Omit to honour the customer record's own
billing default. customer arms the check payment-pending and emails a
pay link — the customer pays by card at the portal.
organization, customer Automated lane only — whether to email the link (default true). When
false the link is returned in verification_link for you to deliver.
Optional note included in the verification email.
2000Optional enhanced due-diligence add-ons to bill alongside the check.
An enhanced due-diligence add-on check.
SOURCE_OF_FUNDS, SOURCE_OF_WEALTH, BIOMETRIC_VERIFICATION Response
The customer record after arming, plus verification_link when a
portal link was generated (the automated lane).
Instant Compliance customer UUID.
Individual customer types — /customers only ingests these.
Entity customers (companies, trusts, partnerships, SMSFs) live on
/entities with their own EntityType.
INDIVIDUAL, SOLE_TRADER NOT_STARTED, PENDING, IN_PROGRESS, VERIFIED, FAILED, NOT_REQUIRED, AWAITING_RESUBMISSION Show child attributes
Show child attributes
How the record entered Instant Compliance.
ADMIN_MANUAL, AI_EXTRACTED, CONTACT_PORTAL, BULK_IMPORT, INTEGRATION, SYSTEM Populated only when kyc_status = VERIFIED. Deliberately minimal —
full date of birth and full address are never exposed.
Show child attributes
Show child attributes
Shareable portal link (automated lane only).

