PUT /customers/:id/kyc/profile
Replace the customer's profile body. The body is polymorphic: it must match the type the customer was created with. Pass a KycProfile under profile for an individual, a KybProfile under profile for a business. Posting the wrong type for the customer's record returns 400.
Every leaf is optional, the wizard saves partial drafts as the user works through it, and the server stores whatever's in the body without checking for completeness. Required-field enforcement runs on POST /customers/:id/kyc/submit.
PUT replaces the saved profile with the request body. To accumulate a draft across multiple steps, fetch with GET /customers/:id/kyc/profile, merge in the new fields client-side, and PUT the merged document.
Saving is always available, whatever the customer's verification status — a saved profile is a draft and files nothing upstream. Submission is what's gated: a customer who is already submitted, under_review, or approved keeps that verification until an explicit submit, and a terminally_rejected or paused customer can be edited but never resubmitted.
Request body
Send an envelope containing type and profile, even for a partial draft. type must be individual or business. Sending profile fields directly at the top level fails because profile is missing.
documents.supporting_documents is read-only: upload or delete supporting evidence through the documents endpoints. A profile PUT cannot replace or clear that list.
A partial or complete profile, polymorphic on type:
When type: "individual"
{
"type": "individual",
"profile": {
"identity": {
"first_name": "Alice",
"last_name": "Liddell"
}
}
}See KycProfile for the full schema.
When type: "business"
{
"type": "business",
"profile": {
"business": {
"legal_name": "Acme Inc."
}
}
}See KybProfile for the full schema.
The type on the body must match the type the customer was created with.
Response 200
The updated profile in the same { type, profile, kyc_link } envelope as GET /customers/:id/kyc/profile (canonicalized: defaults filled in, addresses normalized). The kyc_link field is server-managed and not part of the upsert surface. Callers send { type, profile } only and receive the link back in the response.
Errors
400: body schema invalid, or thetypedoesn't match the customer's kind (e.g. postingtype: "business"on an individual).403: caller does not own the customer.404: unknown customer id.
Example: individual draft fragment
curl -X PUT "$SEISMIC_ORCHESTRATION_URL/v0/customers/$CUSTOMER_ID/kyc/profile" \
-H "Api-Key: $SEISMIC_ORCHESTRATION_API_KEY" \
-H "content-type: application/json" \
--data '{
"type": "individual",
"profile": {
"identity": {
"first_name": "Alice",
"last_name": "Liddell"
}
}
}'Example: business draft fragment
curl -X PUT "$SEISMIC_ORCHESTRATION_URL/v0/customers/$CUSTOMER_ID/kyc/profile" \
-H "Api-Key: $SEISMIC_ORCHESTRATION_API_KEY" \
-H "content-type: application/json" \
--data '{
"type": "business",
"profile": {
"business": {
"legal_name": "Acme Inc.",
"entity_type": "c_corporation"
}
}
}'