Onboarding a Customer

From creating a customer to getting it approved.

There are six calls and they run in order. Read the requirements, create the customer and fill in the profile. Then send the information, upload the files and submit.

The order matters in two places, and both are marked below.

1. Read what's required

GET /v1/kyc/requirements/{country}
GET /v1/kyc/requirements/{country}?type=INDIVIDUAL

Do this before you collect anything. The requirement set tells you which fields and which documents this country needs, so you build your form from the API rather than from a spec that drifts.

There's no separate individual-requirements endpoint. Use ?type=INDIVIDUAL on the same one.

2. Create the customer

POST /v1/customers
{
  "type": "BUSINESS",
  "name": "Andes Trading S.A.S.",
  "email": "[email protected]"
}

Only type is required. It decides whether the customer runs KYC or KYB and can't be changed later, so get it right. There's no parentId, because your API key is the parent.

The customer comes back as NOT_STARTED.

3. Fill in the profile

PUT /v1/customers/{customerId}

This is the call that does the real work. Everything that classifies a customer lives here:

  • The classification fields are customerType, accountType, customerArchetypes and useCases. The KYC reliance model is not among them. It is set by your partner relationship with Alfred rather than per customer.
  • Legal identity covers the registered name, trade name and business type. It also covers the incorporation country and date, and the registration number.
  • Addresses have four separate roles: registered, physical, mailing and tax.
  • Declared activity covers source of funds, source of wealth, expected monthly volume and operating countries. It also covers whether the customer acts on its own behalf and the rest of the risk profile.
  • accountPurposes decides which kinds of virtual account you'll be allowed to create later. Work it out now rather than discovering the constraint at instrument time.
  • industryCodes and the risk flags are what eligibility is decided on, as the next part explains.

Nothing verifies until this is populated.

Who can be onboarded

Alfred evaluates each customer against the rules of every market it will operate in, before any rail access. You supply industryCodes and the profile. The decision is Alfred's. Two lists apply in every market.

ListWhat's on it
Prohibited jurisdictionsAfghanistan, Belarus, Congo, Cuba, the Gaza Strip, Iran, Iraq, Lebanon, Libya, Myanmar, North Korea, the Russian Federation, Somalia, South Sudan, Sudan, Syria, the Ukrainian territories, Venezuela, the West Bank and Yemen
Prohibited industriesUnlawful or abusive activity, fraud, gambling and online gaming, intellectual-property infringement, check cashing, bail bonds, collection agencies, counterfeit or unauthorized goods, drugs, adult content, multi-level marketing, undisclosed money services or money transmission, and precious metals

Alfred may also decline a business it considers to pose elevated financial risk or legal liability, or to breach card-network rules or bank policy. Screen against both lists before you create the customer.

4. Send the information

POST /v1/customers/{customerId}/kyb
POST /v1/customers/{customerId}/kyc

This sends everything except files in one declaration. For a business that means the entity and all its related persons together, so there's no separate roster call.

Each customer has one draft. Posting again before you submit the verification replaces that draft instead of creating a second one. After submission the draft is frozen, and posting again returns submission_frozen.

This has to happen before you upload documents. The response carries a relatedPersonId for each person, and person-level uploads need those IDs.

Getting the roles right

Each related person carries ownershipPercentage and roles. Compliance acts on the two together.

RoleMeaning
ULTIMATE_BENEFICIAL_OWNEROwns at or above the country's threshold
SHAREHOLDEROwns below the threshold
CONTROLLING_PERSONControl without qualifying ownership
DIRECTORBoard role
LEGAL_REPRESENTATIVEAuthorized to bind the entity

Every business needs a beneficial owner, a control person and a signer. At least one related person carries ULTIMATE_BENEFICIAL_OWNER, at least one carries CONTROLLING_PERSON and at least one carries LEGAL_REPRESENTATIVE. One person can hold several roles. Until someone carries LEGAL_REPRESENTATIVE, preflight reports persons.signer as outstanding.

The beneficial ownership threshold depends on the country. Ownership drives the UBO test, and the two have to agree, so anyone at or above the threshold is ULTIMATE_BENEFICIAL_OWNER, not SHAREHOLDER. The percentages across the roster don't need to sum to 100.

CountryA beneficial owner holds
Colombia5% or more, whatever their nationality
Argentina10% or more of the capital or voting rights. If no one reaches it, the person in charge of management, administration or representation is the beneficial owner
Every other country25% or more

Identifiers

The business and each person are identified separately. An owner's identifier never replaces the business's tax identifier, and one identifier type never stands in for another. An RFC is not a CURP, and a passport is not a tax identifier.

Every beneficial owner needs an identity document and a tax identifier. Whether an owner is a US person is decided by the individual, not by where the business is incorporated.

WhoIdentifier
The businessIts tax identifier: RFC, CUIT, NIT, CNPJ, or EIN for a US-formed business
A beneficial owner in ColombiaCC or CE. A passport only where the approved profile allows it
A beneficial owner in ArgentinaCUIT, CUIL or CDI, plus a self-declared PEP status
A beneficial owner in BrazilCPF
A US beneficial ownerSSN. An ITIN only where the approved profile allows it
Any other beneficial ownerA passport, plus the tax identifier of their own jurisdiction

Tax identifiers are validated, including the check digit. A malformed RFC, CUIT, NIT, CNPJ or CPF is refused with 422 validation_error. A missing mandatory identifier blocks the affected product, and it cannot be cleared by entering a different document number.

5. Upload the files

POST /v1/customers/{customerId}/documents
POST /v1/persons/{relatedPersonId}/documents

Uploads are multipart and take one file per call. The maximum size is 10 MB, and the accepted formats are PDF, JPEG or PNG.

A document is filed by what it evidences rather than by a single type, so purposes[] takes several values and one incorporation document can satisfy more than one requirement.

Send purposes in lowercase, using the names preflight reports. An outstanding document comes back from preflight as documents.incorporation, so the purpose to send is incorporation. These are the common ones.

Filed againstPurposeWhat it is
The customerincorporationCertificate or deed of incorporation
The customerproof_of_addressProof of the registered or physical address
The customerproof_of_business_activityEvidence the business operates as declared
A related persongovernment_idFront of a government-issued ID
A related persongovernment_id_backBack of the same ID

6. Check, then submit

POST /v1/customers/{customerId}/verifications/preflight
POST /v1/customers/{customerId}/verifications

Run preflight every time. It evaluates the draft and the uploads against the requirement set and tells you what's still outstanding, while everything is still editable. Fixing those items before you submit saves a rejection round trip. Preflight changes nothing and takes no idempotency key.

Then submit the verification. There's no body, because the customer has exactly one draft. Submitting freezes that draft, creates the verification and starts the review.

Wait on customer.verification.updated.

Reading where it got to

Watch the customer's own status. It tells you who has to act.

StatusMeansWho acts
INCOMPLETEFields or documents are missing. Preflight names which ones.You
AWAITING_UBOThe person roster is incomplete or unverified.You
AWAITING_QUESTIONNAIREDeclared-activity answers are outstanding.You
UNDER_REVIEWSubmitted and being decided.Alfred, unless an RFI is open
ACTIVEApproved.Nobody
REJECTEDTerminal.Nobody

When a reviewer asks for something

That's an RFI, and it's scoped to the customer.

GET  /v1/customers/{customerId}/rfis?status=OPEN
POST /v1/rfis/{rfiId}/evidence

Each RFI names exactly what's needed in requirements[]. Answer with fields keyed by those names, plus any documentIds from an upload. That moves it to RECEIVED.

Read rfi_owner before chasing anyone. Under a reliance model the answer is often owed by you instead of by your end customer, and WAITING_ON_PARTNER is what says so. OVERDUE is not a soft status. A missed SLA is blocking.

Wait on rfi.updated.

Changing something afterwards

POST /v1/customers/{customerId}/reevaluate

Use this for corrected data, a new document or a changed archetype. Update through the normal endpoints and then re-evaluate.

Never submit a second verification.

Letting Alfred collect it instead

POST /v1/customers/{customerId}/onboarding-link
GET  /v1/customers/{customerId}/onboarding-session

This mints a link your end customer opens themselves. They do identity capture, documents and the selfie directly with Alfred, so you never handle document images.

It's worth defaulting to for individual KYC. The alternative is building document capture and liveness for every country template yourself.

The response gives you a full url to send the customer to, a sessionId, and an expiresAt. The link carries its own expiry, so read the value rather than assuming a window.

A customer can have only one session at a time, and a new link supersedes the previous one.

Reading progress. GET /v1/customers/{customerId}/onboarding-session returns where the customer has got to, at two levels of detail.

FieldWhat it tells you
statusCREATED, OPENED, IN_PROGRESS, SUBMITTED, COMPLETED, EXPIRED or ABANDONED
steps[]Each step by name, with its own status, in order
verificationIdSet once the session has been submitted and a verification exists
linkExpiresAtWhen the link stops working
lastActivityAtWhen the customer last did something, which is how you tell abandoned from slow

The steps are IDENTITY, DOCUMENTS, SELFIE, QUESTIONNAIRE and REVIEW. Each one is PENDING, IN_PROGRESS, COMPLETED or SKIPPED. Progress is recorded on the session rather than on the link, which is what lets you see how far someone got.

Subscribe to customer.verification.updated rather than polling this.


Did this page help you?