Customers
Customers represent shoppers who have created an account in your store. A customer carries email, addresses, OAuth provider connections, saved payment methods, and order history. Use these endpoints to manage customer profiles, look up orders, and run the customer authentication flow (login, register, password reset, OAuth).
Register customer
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Customer email, unique per store. Becomes the login identifier.
Password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthFirst name.
Last name.
Phone number (E.164 format recommended).
Marketing consent flag (gates promo emails / SMS).
Birthday month (1-12) for the loyalty birthday gift. Month and day only, with no year. Send it together with birthDay or not at all. Optional on most channels; a channel with requireBirthday turned on rejects a registration that omits it.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31Privacy-policy acceptance flag, required by some stores before account creation. The frontend should require this checkbox when the store enables it.
Loyalty referral share code (REF-XXXXXXXX) from a referrer's link. Validated asynchronously after registration, so an invalid code never fails the registration itself.
curl -X POST "https://api.brainerce.com/api/vc/string/customers/register" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2026-10-07T09:00:00.000Z",
"requiresVerification": false
}Sign in customer
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Customer email address used at registration.
Customer password (plaintext over HTTPS, and never logged).
curl -X POST "https://api.brainerce.com/api/vc/string/customers/login" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2026-10-07T09:00:00.000Z",
"requiresVerification": false
}Reset password
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Email address to send the password-reset link to. Endpoint always responds 200 (no enumeration); the email is only sent if a matching customer exists.
curl -X POST "https://api.brainerce.com/api/vc/string/customers/forgot-password" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"message": "If an account exists, a password reset email has been sent"
}Reset password
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Single-use reset token from the password-reset email. Tokens expire after 1 hour and are invalidated on use.
New password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthcurl -X POST "https://api.brainerce.com/api/vc/string/customers/reset-password" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{ "token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6", "newPassword": "CorrectHorse-Battery-Staple9" }'{
"message": "If an account exists, a password reset email has been sent"
}Get customer profile
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me" \ -H "origin: string" \ -H "authorization: string"{
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"emailVerified": true,
"birthMonth": 4,
"birthDay": 17
}Update customer profile
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
First name.
Last name.
Phone number (E.164 format recommended).
Marketing consent flag, set by the customer themselves.
Birthday month (1-12). Month and day only, with no year: the birthday exists for the loyalty gift, and a year would be date-of-birth data we have no reason to hold. Send it together with birthDay or not at all, and send null for both to remove a stored birthday.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all, and send null for both to remove a stored birthday. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31curl -X PATCH "https://api.brainerce.com/api/vc/string/customers/me" \ -H "origin: string" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": false,
"birthMonth": 4,
"birthDay": 17,
"role": "wholesale",
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"createdAt": "string",
"updatedAt": "string"
}Get checkout prefill data
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/checkout-prefill" \ -H "origin: string" \ -H "authorization: string"{
"customer": {
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"emailVerified": true,
"birthMonth": 4,
"birthDay": 17
},
"defaultAddress": {
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
},
"shippingAddress": {
"email": "string",
"firstName": "string",
"lastName": "string",
"company": "string",
"line1": "string",
"line2": "string",
"city": "string",
"region": "string",
"postalCode": "string",
"country": "string",
"phone": "string"
}
}Get customer cart
Returns the logged-in customer's active cart, creating one if none exists. Requires a customer Bearer token in the Authorization header.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Header Parameters
Customer Bearer token (Bearer <token>).
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/cart" \ -H "origin: string" \ -H "authorization: string"{
"id": "clcrt_abc123",
"sessionToken": "string",
"customerId": "string",
"status": "ACTIVE",
"currency": "USD",
"notes": "string",
"analyticsClientId": "string",
"analyticsSessionId": "string",
"subtotal": "39.80",
"discountAmount": "5.00",
"ruleDiscountAmount": "0",
"promoDiscountTotal": "0",
"couponCode": "WELCOME10",
"appliedDiscounts": [
{
"ruleId": "cldr_abc123",
"ruleName": "string",
"type": "PERCENTAGE_OFF",
"discountAmount": "5.00",
"description": "string"
}
],
"nudges": [
{
"ruleId": "cldr_abc123",
"text": "string",
"type": "AMOUNT_NEEDED",
"amountNeeded": "12.00",
"quantityNeeded": 1
}
],
"items": [
{
"productId": "clx1234567890",
"variantId": "string",
"quantity": 2
}
],
"itemCount": 3,
"hasPriceChanges": false,
"hasUnavailableItems": false,
"unavailableItemIds": [],
"expiresAt": "string",
"createdAt": "string",
"updatedAt": "string",
"reservation": {
"hasReservation": true,
"expiresAt": "string",
"remainingSeconds": 540,
"strategy": "ON_CART",
"countdownMessage": "string"
},
"recommendations": {},
"upgrades": {},
"bundles": {}
}List customer addresses
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/addresses" \ -H "origin: string" \ -H "authorization: string"[
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
]Add customer address
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Friendly label shown in the address picker UI.
First name on the address.
Last name on the address.
Company name (B2B).
Street address line 1.
Street address line 2 (apt/suite).
City.
State / Province.
Postal / ZIP code.
ISO 3166-1 alpha-2 country code.
Phone (E.164 recommended).
Mark this address as the customer's default. Promoting a new default automatically demotes the previous one.
curl -X POST "https://api.brainerce.com/api/vc/string/customers/me/addresses" \ -H "origin: string" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "line1": "123 Main St", "city": "San Francisco", "postalCode": "94103", "country": "US" }'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}Update customer address
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
Friendly label.
First name.
Last name.
Company.
Street line 1.
Street line 2.
City.
State / Province.
Postal / ZIP.
ISO country code.
Phone.
Promote this address to be the customer's default.
curl -X PATCH "https://api.brainerce.com/api/vc/string/customers/me/addresses/string" \ -H "origin: string" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}Delete customer address
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X DELETE "https://api.brainerce.com/api/vc/string/customers/me/addresses/string" \ -H "origin: string" \ -H "authorization: string"{
"success": true
}List customer orders
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Query Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/orders?page=string&limit=string" \ -H "origin: string" \ -H "authorization: string"{
"data": [
{
"id": "clord_abc123",
"orderNumber": "ORD-20260907-0012",
"status": "processing",
"totalAmount": "46.96",
"subtotal": "39.80",
"discountAmount": "0",
"couponCode": "WELCOME10",
"couponDiscount": "string",
"ruleDiscountAmount": "string",
"appliedDiscounts": [
{}
],
"shippingAmount": "5.00",
"taxAmount": "0",
"currency": "ILS",
"createdAt": "string",
"itemCount": 2,
"items": [
{
"productId": "clprd_abc123",
"variantId": "string",
"sku": "string",
"name": "string",
"quantity": 2,
"price": "19.90",
"unitPrice": "19.90",
"totalPrice": "39.80",
"image": "string",
"customizations": {},
"modifiers": [
{}
]
}
],
"hasDownloads": false,
"notes": "string",
"tenders": [
{
"id": "cltnd_abc123",
"type": "GIFT_CARD",
"amountBase": "25.00",
"currencyBase": "ILS",
"giftCard": {}
}
]
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 137,
"totalPages": 14
}
}List order downloads
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Query Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/orders/string/downloads?checkout_id=string" \ -H "origin: string" \ -H "authorization: string"[
{
"productName": "Wallpaper pack",
"fileName": "wallpapers.zip",
"downloadUrl": "https://api.brainerce.com/api/stores/clst_abc/downloads/eyJ...",
"downloadsUsed": 0,
"downloadLimit": 5,
"expiresAt": "string"
}
]Verify email
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
6-digit verification code from the email-verification message. Codes expire after 15 minutes.
6 <= lengthcurl -X POST "https://api.brainerce.com/api/vc/string/customers/verify-email" \ -H "origin: string" \ -H "authorization: string" \ -H "Content-Type: application/json" \ -d '{ "code": "482917" }'{
"verified": true,
"message": "Email verified",
"customer": {
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "string",
"requiresVerification": true
}Resend verification email
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X POST "https://api.brainerce.com/api/vc/string/customers/resend-verification" \ -H "origin: string" \ -H "authorization: string"{
"message": "Verification email sent",
"token": "string"
}List o auth providers
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/oauth/providers" \ -H "origin: string"{
"providers": [
"GOOGLE",
"FACEBOOK"
]
}Get o auth authorize url
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Query Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/oauth/string/authorize?redirectUrl=string" \ -H "origin: string"{
"authorizationUrl": "string",
"state": "string",
"provider": "GOOGLE"
}Handle o auth callback
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Query Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/oauth/string/callback?code=string&state=string&error=string&error_description=string" \ -H "origin: string"{
"error": "access_denied",
"errorDescription": "string",
"provider": "GOOGLE",
"customer": {
"id": "clcus_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "string",
"isNewCustomer": false,
"linkedToExisting": true,
"redirectUrl": "/account"
}List customer o auth connections
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/customers/me/oauth-connections" \ -H "origin: string" \ -H "authorization: string"{
"connections": [
{
"id": "cloac_abc123",
"provider": "GOOGLE",
"email": "[email protected]",
"createdAt": "string"
}
]
}Link o auth provider
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Query Parameters
Header Parameters
curl -X POST "https://api.brainerce.com/api/vc/string/oauth/string/link?redirectUrl=string" \ -H "origin: string" \ -H "authorization: string"{
"authorizationUrl": "string",
"state": "string",
"provider": "GOOGLE"
}Unlink o auth provider
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Header Parameters
curl -X DELETE "https://api.brainerce.com/api/vc/string/oauth/string/link" \ -H "origin: string" \ -H "authorization: string"{
"success": true
}List contact forms
Returns the contact forms the merchant has published to this sales channel — key, name and description only, not the field schema. Fetch the schema for one form with GET /contact-forms/{formKey}, then submit it to POST /inquiries. Every store has a form keyed main; a merchant can add more (a support form, a wholesale enquiry form) and this list is how you discover them. Inactive forms are omitted. Rate limited to 60 requests per minute.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/contact-forms" \ -H "origin: string"[
{
"key": "main",
"name": "Contact us",
"isDefault": true
}
]Get contact form schema
Returns the full field schema for one contact form: every field's key, type, label, placeholder, whether it is required, and its validation bounds. Render one control per field in the order given, then submit the collected values as the fields object of POST /inquiries — the server re-validates against this same schema and strips unknown keys, so a form built from a stale copy of the schema will have values silently dropped. Labels and placeholders come back translated for locale, falling back to the store language. Rate limited to 60 requests per minute.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Form to fetch, as listed by GET /contact-forms. An empty segment resolves to the default form, main.
Query Parameters
Locale for translated labels and placeholders (e.g. "he"). Falls back to the store language.
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/contact-forms/main?locale=string" \ -H "origin: string"{
"id": "clcf_abc123",
"key": "main",
"name": "string",
"description": "string",
"submitButton": "Send",
"successMessage": "Thanks, we will be in touch.",
"fields": [
{
"key": "message",
"type": "TEXTAREA",
"label": "Your message",
"placeholder": "string",
"helpText": "string",
"isRequired": true,
"enumValues": [
{
"value": "red",
"label": "Red"
}
],
"validation": {
"minLength": 2,
"maxLength": 500,
"min": 1,
"max": 99,
"pattern": "string",
"patternMessage": "string"
},
"defaultValue": "string",
"width": "FULL"
}
]
}Create inquiry
Submits a contact-form message to the merchant. Two payload shapes are accepted. The modern one is formKey plus a fields object keyed by the field keys returned by GET /contact-forms/{formKey} — every value is re-validated against that schema server-side and unknown keys are stripped. The legacy flat shape (name, email, subject, message, phone) is still accepted for older storefronts. A request may send both; fields wins and the flat fields fill in whatever it omits.
No authentication. Include the honeypot field in your markup as a hidden, empty input — any non-empty value rejects the request. Rate limited to 3 submissions per minute, which is deliberately tight: this route mails the merchant.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Header Parameters
Sender name. Legacy flat shape — prefer fields keyed by the form schema. Mirrored onto the same column fields.name writes, so sending both is redundant, not additive.
length <= 120Sender email, so the merchant can reply. Legacy flat shape — prefer fields.
length <= 254Subject line. Legacy flat shape — prefer fields.
length <= 200Message body. Legacy flat shape — prefer fields.
length <= 10000Sender phone number, when the form collects one. Legacy flat shape.
length <= 40Which contact form this submission belongs to, as listed by GET /contact-forms. Defaults to main. Lowercase letters, digits, _ and -; must start with a letter.
^[a-z][a-z0-9_-]{0,39}$The submitted values, keyed by the field keys from GET /contact-forms/{formKey}. Every value is re-validated against that form's schema server-side and any key the schema does not declare is STRIPPED SILENTLY — a form built from a stale schema loses those values without an error. This is the preferred shape; the flat fields above exist only for older storefronts.
Empty Object
Storefront locale at submission time (e.g. "he"). Sets the language of the confirmation email and how the inquiry is displayed to the merchant. Falls back to the store language.
length <= 10Arbitrary provenance: referrer, UTM parameters, the page the form sat on. Stored as JSON for your own reporting, never interpreted.
Empty Object
Logged-in customer this inquiry belongs to, when the storefront knows one. Optional — contact forms are open to guests.
length <= 120Arbitrary key/value data stored alongside the inquiry.
Empty Object
Anti-bot honeypot. Render it hidden and leave it empty; a filled value rejects the request. Bots complete every text input, humans never see this one.
curl -X POST "https://api.brainerce.com/api/vc/string/inquiries" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "clinq_abc123",
"status": "NEW",
"createdAt": "string"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/vc/{connectionId}/inquiries"
}Subscribe to marketing email
Signs an address up for the store's marketing email — the newsletter popup, the footer capture bar, an exit-intent modal.
This does NOT grant consent. It creates the contact and mails a confirmation link, and the address stays unmailable until the recipient clicks it, so a forged or mistyped submission costs one email and nothing more. Do not tell the shopper they are subscribed; tell them to check their inbox.
The response is identical whatever the address's history — already subscribed, already a customer, entirely unknown — so the endpoint cannot be used to probe who shops at this store. A per-address cooldown suppresses repeat confirmation mail to the same victim.
No authentication. Include the honeypot field as a hidden, empty input. Rate limited to 3 requests per minute.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Header Parameters
Address to subscribe. Lowercased and trimmed server-side. A confirmation email is sent to it; consent is granted only when that link is clicked.
length <= 254Given name, when the form collects one. Greets the recipient in the confirmation email and is stored on the customer record.
length <= 100Family name, when the form collects one.
length <= 100Storefront locale at submission time (e.g. "he"). Picks the language of the confirmation email and is saved as the preferred locale on a newly created customer. Falls back to the store language.
length <= 10Where on the storefront the signup came from, such as "popup", "footer", or "exit-intent". Free-form; stored for your own reporting, never interpreted.
length <= 60Arbitrary provenance: referrer, UTM parameters, the page the popup fired on. Stored as JSON on a newly created customer record.
Empty Object
Anti-bot honeypot. Render it hidden and leave it empty; a filled value rejects the request. Bots complete every text input, humans never see this one.
curl -X POST "https://api.brainerce.com/api/vc/string/marketing/subscribe" \ -H "origin: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"ok": true
}Read the newsletter signup benefit
The offer to show beside a newsletter signup field: the discount, how long the coupon lasts, any minimum order, whether it is limited to a first order, and the merchant-written headline and terms.
Returns null when the store offers no benefit — render the plain signup form in that case, and do not promise anything.
Show these terms on the form, then post to /marketing/subscribe. The coupon does not exist yet at that point: it is created only when the shopper clicks the link in the confirmation email, and it is then emailed to them. Tell them to check their inbox rather than telling them they have a coupon.
Carries no information about any individual and accepts no email address, so it cannot be used to check whether someone has already subscribed or already claimed a benefit.
For /api/vc/{connectionId}/* routes the connectionId (vc_*) is in the URL path — not a header. Live-mode requests must also send a matching Origin header.
In: header
Path Parameters
Sales-channel connection ID (vc_*)
Query Parameters
Header Parameters
curl -X GET "https://api.brainerce.com/api/vc/string/newsletter-benefit?locale=string" \ -H "origin: string"Read the active newsletter signup benefit
The offer to show beside a newsletter signup field: discount, validity, minimum order, whether it is first-order only, and the merchant-written headline and terms.
Returns null when no benefit is active — render the plain signup form in that case.
Carries no information about any individual and accepts no email address, so it cannot be used to test whether someone has already subscribed or claimed. Tell the shopper the terms shown here, then post to /marketing/subscribe; the coupon only exists after they click the link in the confirmation email.
Path Parameters
Store ID
Query Parameters
Preferred language for the headline and terms. Falls back to the store language.
curl -X GET "https://api.brainerce.com/api/stores/string/newsletter-benefit?locale=string"Create a new customer
Honors Idempotency-Key header. See /docs/api/idempotency.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Customer email, unique per store. Used for login (when password is set) and order lookup.
Phone number (E.164 format recommended for SMS notifications).
First name.
Last name.
Plaintext password. When provided, the customer is created as a registered account (can log in). When omitted, a guest record is created (orders can still link by email).
8 <= lengthMarketing consent flag. Required for transactional vs marketing email split.
Birthday month (1-12) for the loyalty birthday gift. Month and day only, with no year. Send it together with birthDay or not at all; one without the other is rejected.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31Free-form tags for segmentation (VIP, B2B, beta-tester, …).
Free-form customer segment/role set by the merchant (e.g. "wholesale", "vip", "ambassador"). Returned on /customers/me so storefront code can branch on it to build custom, role-gated features. Not settable by the customer themselves: admin dashboard/API only.
length <= 50FIRST-TOUCH sales channel for a customer being created here. Creating a customer through the dashboard or API is not itself a channel sighting, so this stays null unless you say otherwise. Set it when you know where the person actually came from (migrating from another system, a phone order taken for a specific storefront). Accepts the internal SalesChannel id or the public vc_* connectionId. Attach them to the channels they SHOP on separately, via the publish endpoint.
Arbitrary JSON metadata. Useful for storing integration-specific IDs (your ERP customer number, CRM contact id, …).
Empty Object
curl -X POST "https://api.brainerce.com/api/v1/customers" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers"
}Get a customer by ID
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
curl -X GET "https://api.brainerce.com/api/v1/customers/string"{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z",
"marketingStatus": "SUBSCRIBED"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}Update a customer
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Customer email. Changing email re-triggers verification (the new address must be verified before sensitive operations).
Phone number.
First name.
Last name.
Marketing consent flag.
Birthday month (1-12) for the loyalty birthday gift. Month and day only, no year. Send null for BOTH fields to remove a stored birthday; sending neither leaves it untouched, so an edit form that simply omits an emptied field can correct a birthday but never clear one.
Birthday day of month (1-31). Send null for BOTH fields to remove a stored birthday; sending neither leaves it untouched, so an edit form that simply omits an emptied field can correct a birthday but never clear one.
Replace the customer's tag list. Pass [] to clear all tags.
Free-form customer segment/role set by the merchant (e.g. "wholesale", "vip", "ambassador"). Pass an empty string to clear it. Not settable by the customer themselves: admin dashboard/API only.
length <= 50Override the FIRST-TOUCH sales channel, the channel this customer came in through. Normally stamped automatically at registration / OAuth / checkout and then never changed; this is the merchant correction for customers created from the dashboard or imported from a file, where no channel was ever known. Accepts the internal SalesChannel id or the public vc_* connectionId. Pass an empty string to clear it back to "unknown". Does NOT change which channels the customer is active in: that is the publish/unpublish endpoints.
Replace metadata JSON (full replacement, not merge).
Empty Object
curl -X PATCH "https://api.brainerce.com/api/v1/customers/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "cust_abc123",
"email": "[email protected]",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+14155552671",
"hasAccount": true,
"emailVerified": true,
"acceptsMarketing": true,
"birthMonth": 4,
"birthDay": 17,
"tags": [
"vip",
"newsletter"
],
"role": "wholesale",
"totalOrders": 12,
"totalSpent": "1284.50",
"lastOrderAt": "2026-05-10T14:32:11.000Z",
"rfm": {
"r": 5,
"f": 4,
"m": 5,
"score": "5-4-5",
"segment": "champion"
},
"createdAt": "2025-08-01T09:00:00.000Z",
"loyaltyPointsBalance": 240,
"isLoyaltyMember": true,
"acquisitionSalesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"channelPublishes": [
{
"salesChannel": {
"id": "clsc_abc123",
"name": "Main storefront",
"connectionId": "vc_3n8Xk2p9QwErTyUiOpAsD"
},
"firstSeenAt": "2026-03-04T08:12:00.000Z",
"lastSeenAt": "2026-08-11T19:40:22.000Z"
}
],
"metadata": {
"erpId": "CUST-00421"
},
"loyaltyMembershipId": "clmem_abc123",
"platformConnections": [
{
"platformCode": "shopify",
"externalId": "7654321098765"
}
],
"addresses": [
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
],
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}"
}Get a customer by email
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Query Parameters
curl -X GET "https://api.brainerce.com/api/v1/customers/by-email?email=string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/by-email"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/by-email"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/by-email"
}Customer login
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Customer email address used at registration.
Customer password (plaintext over HTTPS, and never logged).
curl -X POST "https://api.brainerce.com/api/v1/customers/login" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "string",
"email": "[email protected]",
"firstName": "string",
"lastName": "string",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2019-08-24T14:15:22Z",
"requiresVerification": true
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/login"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/login"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/login"
}Customer registration
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Customer email, unique per store. Becomes the login identifier.
Password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthFirst name.
Last name.
Phone number (E.164 format recommended).
Marketing consent flag (gates promo emails / SMS).
Birthday month (1-12) for the loyalty birthday gift. Month and day only, with no year. Send it together with birthDay or not at all. Optional on most channels; a channel with requireBirthday turned on rejects a registration that omits it.
1 <= value <= 12Birthday day of month (1-31). Send it together with birthMonth or not at all. The day must exist in that month, so 30 February is rejected.
1 <= value <= 31Privacy-policy acceptance flag, required by some stores before account creation. The frontend should require this checkbox when the store enables it.
Loyalty referral share code (REF-XXXXXXXX) from a referrer's link. Validated asynchronously after registration, so an invalid code never fails the registration itself.
curl -X POST "https://api.brainerce.com/api/v1/customers/register" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]", "password": "CorrectHorse-Battery-Staple9" }'{
"customer": {
"id": "string",
"email": "[email protected]",
"firstName": "string",
"lastName": "string",
"phone": "string",
"emailVerified": true
},
"token": "string",
"expiresAt": "2019-08-24T14:15:22Z",
"requiresVerification": true
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/register"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/register"
}Request password reset
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Email address to send the password-reset link to. Endpoint always responds 200 (no enumeration); the email is only sent if a matching customer exists.
curl -X POST "https://api.brainerce.com/api/v1/customers/forgot-password" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "email": "[email protected]" }'{
"message": "If an account exists with that email, a reset link has been sent"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/forgot-password"
}Reset password with token
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Single-use reset token from the password-reset email. Tokens expire after 1 hour and are invalidated on use.
New password (≥ 8 chars, must match PASSWORD_REGEX: at least one uppercase, lowercase, number, and special char).
8 <= lengthcurl -X POST "https://api.brainerce.com/api/v1/customers/reset-password" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6", "newPassword": "CorrectHorse-Battery-Staple9" }'{
"message": "If an account exists with that email, a reset link has been sent"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/reset-password"
}{
"statusCode": 429,
"code": "RATE_LIMITED",
"message": "Too many requests",
"details": {
"retryAfterSeconds": 12
},
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/reset-password"
}Get customer addresses
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
curl -X GET "https://api.brainerce.com/api/v1/customers/string/addresses"[
{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}
]{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}Add a customer address
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Friendly label shown in the address picker UI.
First name on the address.
Last name on the address.
Company name (B2B).
Street address line 1.
Street address line 2 (apt/suite).
City.
State / Province.
Postal / ZIP code.
ISO 3166-1 alpha-2 country code.
Phone (E.164 recommended).
Mark this address as the customer's default. Promoting a new default automatically demotes the previous one.
curl -X POST "https://api.brainerce.com/api/v1/customers/string/addresses" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{ "firstName": "Jane", "lastName": "Doe", "line1": "123 Main St", "city": "San Francisco", "postalCode": "94103", "country": "US" }'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses"
}Update a customer address
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
Address ID
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255Friendly label.
First name.
Last name.
Company.
Street line 1.
Street line 2.
City.
State / Province.
Postal / ZIP.
ISO country code.
Phone.
Promote this address to be the customer's default.
curl -X PATCH "https://api.brainerce.com/api/v1/customers/string/addresses/string" \ -H "Idempotency-Key: string" \ -H "Content-Type: application/json" \ -d '{}'{
"id": "addr_abc123",
"label": "Home",
"firstName": "Jane",
"lastName": "Doe",
"company": "Acme Inc",
"line1": "123 Main St",
"line2": "Apt 4B",
"city": "San Francisco",
"region": "CA",
"postalCode": "94103",
"country": "US",
"phone": "+14155552671",
"isDefault": true,
"createdAt": "2025-08-01T09:00:00.000Z",
"updatedAt": "2026-05-12T11:24:08.000Z"
}{
"statusCode": 400,
"code": "VALIDATION_FAILED",
"message": "name should not be empty, price must be a positive number",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}Delete a customer address
Supports Idempotency-Key header for safe retries.
Admin API key (server-to-server). Issue via the dashboard at Settings → Authentication → API Keys. Plain-text key is shown once — store in a secret manager. Format: Authorization: Bearer brainerce_xxxxxxxxx.
In: header
Path Parameters
Customer ID
Address ID
Header Parameters
Client-supplied key (a UUID v4 is the recommended form, max 255 characters) that makes this mutation safe to retry.
- Replay window: 24 hours. The first response for a key is cached; a retry inside the window with the same request body returns the original status and body without re-running the handler.
- Reusing a key with a different body returns
409 Conflictwithcode: "IDEMPOTENCY_KEY_REUSED". The request fingerprint (method + path + body hash) is compared against the stored one; a mismatch is refused rather than served the old response. - Keys are scoped to the calling credential and store — two API keys may safely use the same key value.
- Error responses are cached too, so a retry of a request that failed validation returns the same 400 immediately.
- Sending this header on a
GETreturns400withcode: "IDEMPOTENCY_KEY_NOT_SUPPORTED"— GETs are already idempotent. - Support is per-route and this parameter is the authoritative signal: a key sent to a route that does not declare it is accepted and silently ignored.
length <= 255curl -X DELETE "https://api.brainerce.com/api/v1/customers/string/addresses/string" \ -H "Idempotency-Key: string"{
"statusCode": 401,
"code": "UNAUTHORIZED",
"message": "Invalid or expired credential",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"statusCode": 403,
"code": "INSUFFICIENT_SCOPE",
"message": "API key does not have the required scope: products:write",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}{
"statusCode": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "Resource not found",
"timestamp": "2026-08-23T10:15:00.000Z",
"path": "/api/v1/customers/{id}/addresses/{addressId}"
}