Update a member's KYC profile directly (partial update)
x-idempotency-key
The merchant server submits JSON directly to update the member's primary KYC profile, without a hosted page. Editable data includes name, sex, date of birth, email, phone, document type and expiry, photos, residence type, and address. identity_number (document number), nationality (nationality), identity_issue_country (document-issuing country), and address_country (country of residence) cannot be changed. Supplying them returns invalid_fields and none of the update is applied. Send only fields to change within profile; omitted data and document photos retain their existing values. An empty string or empty array is an explicit change and remains subject to validation; null does not mean keep unchanged. identity_photos merges subfields, while residence_permit_urls replaces the whole array. An empty profile, unknown fields, invalid phone numbers, or incorrect field types are rejected.
A successful update returns pending and level: 0, sending the profile for review again; KYC records for individual card products also return to pending review. Business requiring a verified KYC level is blocked until approval. This endpoint does not directly update existing cards or upstream cardholder contact details, nor automatically retry failed applications. If issuance failed because the phone number was already in use, change it to the user's real available number, obtain approval, then submit a new card application with a new idempotency key. Reusing the old key returns the original failure.
Review status, KYC level, member ownership, and the quick KYC profile pool cannot be changed. Changing profile.email does not change the account login email. The new contact email must match the account email or be accompanied by a matching email_verify_key. If no profile exists, returns not_found without creating one. Concurrent modifications return state_invalid; resubmit with a new idempotency key.
Request Headers
| Field | Type | Required | Description |
|---|---|---|---|
x-on-behalf-of |
string | Required | The member's external_member_id or mem_<uuid>, not a card application ID. |
x-idempotency-key |
string | Required |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email_verify_key |
string | Optional | Email verification credential used when changing to a new contact email. |
profile |
object | Required | |
profile.first_name |
string | Optional | |
profile.last_name |
string | Optional | |
profile.email |
string | Optional | |
profile.phone |
string | Optional | |
profile.phone_zone_number |
string | Optional | |
profile.identity_type |
string | Optional | |
profile.identity_expiry_date |
string | Optional | |
profile.cardholder_residence |
string | Optional | |
profile.residence_permit_type |
string | Optional | |
profile.sex |
string | Optional | |
profile.occupation |
string | Optional | |
profile.birth_date |
string | Optional | |
profile.address_province |
string | Optional | |
profile.address_city |
string | Optional | |
profile.address_district |
string | Optional | |
profile.address |
string | Optional | |
profile.street_number |
string | Optional | |
profile.postal_code |
string | Optional | |
profile.identity_photos |
object | Optional | |
profile.residence_permit_urls |
string[] | Optional |
Response
{
"kyc_id": "48",
"status": "pending",
"review_status": "UNREVIEWED",
"level": 0
}invalid_request · invalid_fields · member_context_required · state_invalid · request_rejected · idempotency_key_requiredinvalid_token · invalid_signature · signature_requiredinsufficient_scopemember_not_found · not_foundidempotency_key_reusedcurl -X PATCH 'https://api.zinfra.vip/v1/kyc' \
-H 'x-auth-token: Bearer $TOKEN' \
-H 'x-idempotency-key: $IDEMPOTENCY_KEY' \
-H 'content-type: application/json' \
-d '{
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
}'const res = await fetch("https://api.zinfra.vip/v1/kyc", {
method: "PATCH",
headers: {
"x-auth-token": "Bearer $TOKEN",
"x-idempotency-key": "$IDEMPOTENCY_KEY",
"content-type": "application/json",
},
body: JSON.stringify({
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
}),
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();import requests
res = requests.patch(
"https://api.zinfra.vip/v1/kyc",
headers={
"x-auth-token": "Bearer $TOKEN",
"x-idempotency-key": "$IDEMPOTENCY_KEY",
"content-type": "application/json",
},
json={
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
},
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()req, _ := http.NewRequest("PATCH", "https://api.zinfra.vip/v1/kyc",
strings.NewReader(`{
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-idempotency-key", "$IDEMPOTENCY_KEY")
req.Header.Set("content-type", "application/json")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.zinfra.vip/v1/kyc"))
.header("x-auth-token", "Bearer $TOKEN")
.header("x-idempotency-key", "$IDEMPOTENCY_KEY")
.header("content-type", "application/json")
.method("PATCH", HttpRequest.BodyPublishers.ofString("""
{
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
}
"""))
.build();
// Use String / BigDecimal for amounts, not double.$ch = curl_init('https://api.zinfra.vip/v1/kyc');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'x-auth-token: Bearer $TOKEN',
'x-idempotency-key: $IDEMPOTENCY_KEY',
'content-type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"profile": {
"first_name": "Alex",
"occupation": "designer",
"address": "25 Main Street",
"phone_zone_number": "1",
"phone": "2025550123"
}
}
JSON,
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
{
"kyc_id": "48",
"status": "pending",
"review_status": "UNREVIEWED",
"level": 0
}