Skip to main content
Concepts and field guidance in Buyer profiles.

Create

Success: 201.

Body

Every field is optional — {} is a valid profile — but the agent can only fill what you gave it. The top level is strict, exactly like PATCH: an unknown field is a 400 with an unrecognized_keys issue rather than a field we quietly drop, because the field most worth misspelling here is subject, and a 201 carrying an untagged profile is a fence that is not there. The nested name, contact and shipping objects are not strict.
string
Yours, for bookkeeping. Never sent to a merchant.
string
Your own id for the end user this profile belongs to. 1 to 200 characters after trimming, opaque to us, never sent to a merchant. "" is a 400.On a subject-bound key it is filled in for you — omit it and the profile is stamped with the key’s subject; name a different one and the request is a 403. On a tenant-wide key it is how you tag a profile so that a bound key can later reach it and no other end user’s key can.Create-only. PATCH rejects it; a profile cannot be reassigned.
object
Also used as the cardholder name at the payment step, which is why the card action never asks for one.
object
object
No validation beyond types. No normalisation, no address correction — values are stored and typed exactly as sent.

Response

Omitted sub-objects come back as null, not as {}. subject is always present and null on an untagged profile — unlike a checkout, which omits the field entirely. 400 Invalid profile with issues on a type mismatch, an unknown top-level field, or an empty subject.

Get one

Success: 200.
Same object as create. 404 Profile not found if it does not exist, is not yours, or belongs to another end user on a subject-bound key.

List

Success: 200.
integer
default:"20"
Caps at 100. Send an integer.
string
The previous page’s nextCursor — an ISO timestamp. Returns profiles created strictly before it.
Newest first. nextCursor: null means the last page. On a subject-bound key this page contains only that end user’s profiles. There is no ?subject= filter here — unlike the checkout list, which has one — so a tenant-wide key reads subject off each row.

Update

Success: 200, returning the full updated profile.

Body

Same fields as create, all optional — but partial only at the top level.
name, contact and shipping are each one JSON document. Omit a key and that document is untouched; supply a key and its document is replaced wholesale. There is no deep merge.{"shipping":{"postalCode":"NW1 6XE"}} does not change the postcode on the stored address — it throws the address away and stores one that is only a postcode. Send the whole object.
string | null
Replaces the stored label. null clears it.
object | null
Replaces the whole name document. null clears it; {} stores an empty object, which is a different thing.
object | null
Replaces the whole contact document. null clears it.
object | null
Replaces the whole shipping document. null clears it — this is how you remove an address you no longer want us holding, short of deleting the profile.
subject is not accepted here. Both schemas are strict, so this is a 400 rather than a silently dropped field.

Errors

An unexpected key is a 400 rather than a silently dropped field. That is most likely to bite you with subject:
400
A profile cannot be moved to another end user after creation. See End-user isolation.

Delete

Success: 200.
A row delete, not a soft delete. This is the endpoint to call when a buyer asks you to remove what you hold about them. The blast radius is fixed by foreign keys, so it is the same every time: 404 Profile not found covers both “no such id” and “another tenant’s”. A repeat delete is a 404 — treat it as success when retrying.
Deleting a profile does not stop a checkout already running against it. The run loaded the address it needed before this call; the reference simply nulls out. Cancel the checkout as well if nothing more should ship.