Skip to main content

RegisterCustomerInput

Registers a new customer account.

input RegisterCustomerInput {
address: CustomerAddressInput
businessType: BuyerBusinessType
code: String!
companyName: String!
contactName: String!
department: String
email: String!
firstName: String
lastName: String
phone: String
subdomain: String
title: String
whatsapp: String
}

Fields​

RegisterCustomerInput.address ● CustomerAddressInput input​

The registrant's first address, collected as the second step of signup and created in the SAME transaction as the Partner. It rides on registration rather than being added afterwards because a tenant that screens new customers gives them no session — so an address collected after sign-in is an address a PENDING account can never enter. Optional: a tenant that does not screen its customers may also let them skip it and add one later.

RegisterCustomerInput.businessType ● BuyerBusinessType enum​

Whether the registrant is a business or an individual → the Partner.type COLUMN (mirrored onto Partner.metadata.businessType), the SAME field the seller console's customer form edits and myProfile.businessType reads back. Omitted defaults to BUSINESS.

RegisterCustomerInput.code ● String! non-null scalar​

The 6-digit code the registrant already verified on the OTP screen, which now comes BEFORE this form (mirroring the buyer app's email → OTP → details order, owner decision 2026-08-11). Re-checked server-side here because this mutation is what actually creates the account: without it, registration is callable directly and 'verified email' would be a client-side claim (Foundation Gate 3). The code is NOT consumed here — the sign-in that follows spends it.

RegisterCustomerInput.companyName ● String! non-null scalar​

The name of the company.

RegisterCustomerInput.contactName ● String! non-null scalar​

The person's full name. Still REQUIRED — it is what every existing reader renders, and older portal builds send only this. When firstName/lastName are also sent they win, because a split of "Ana Maria Da Silva" can only guess where the surname starts and the form already knows.

RegisterCustomerInput.department ● String scalar​

The person's department (e.g. 'Procurement'). Stored on their Contact rows, like title.

RegisterCustomerInput.email ● String! non-null scalar​

Email address.

RegisterCustomerInput.firstName ● String scalar​

Given name. Optional for older builds sending only contactName; takes precedence over splitting it when present.

RegisterCustomerInput.lastName ● String scalar​

Family name. See firstName.

RegisterCustomerInput.phone ● String scalar​

Mobile number in E.164 form (e.g. +27821234567) → User.phone plus a PHONE Contact channel row.

RegisterCustomerInput.subdomain ● String scalar​

Dev/localhost fallback for multi-tenant resolution — the request host (X-Original-Host → Host) always wins, exactly like checkCustomerExists.

RegisterCustomerInput.title ● String scalar​

The person's job title (e.g. 'Purchasing Manager'). Stored on their Contact rows — there is no title column on User. Same field as MobileRegisterBuyerInput.title.

RegisterCustomerInput.whatsapp ● String scalar​

WhatsApp number in E.164 form. Persisted as its own WHATSAPP Contact channel row — there is no WhatsApp column on User. The portal form offers a "Same as mobile number" tick, exactly like the seller console and the buyer app.

Member Of​

registerCustomer mutation