Core ConceptsCustomers

Customers

Individuals and businesses, and how the customer object doubles as the verification intake.

One object, two kinds

A customer is your end user. kind is required, and there is no default: a silently defaulted individual for a forgotten field is the wrong record to fail into.

{
  "kind": "individual",
  "first_name": "Ana",
  "last_name": "Silva",
  "email": "ana@example.com",
  "phone": "+14155550123",
  "date_of_birth": "1993-04-12",
  "nationality": "US",
  "residence_country": "US",
  "address": {
    "street_line_1": "300 Post St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94108",
    "country": "US"
  },
  "id_document": {"kind": "passport", "number": "P123456"},
  "tax_id": "078-05-1120",
  "tax_residence_country": "US",
  "tos_acceptance": {"ip_address": "203.0.113.7"},
  "partner_reference_id": "user-8213"
}

Only a terms path is strictly required. Names are not, so that a partially known person can exist as a legal record before they can transact. middle_name is accepted beside the other two.

Most of this can come from the images instead. At submit we read the identity document, the proof of address, and a proof of tax identification if you send one, then fill only the fields you left empty: the names, date of birth, nationality, the identity document's kind and number, the address, and the tax data. A value you send is never overwritten. Anything the documents cannot supply surfaces in a requirement bucket. See Documents are read at submit.

Responses omit the other kind's fields entirely. An individual payload has no legal_name key at all, rather than a null.

People on a business

Every controller gets an id (ctl_...), and the customer object lists each one with that id, the names, and the roles:

"controllers": [
  {
    "id": "ctl_033y2KpQ7vLmN8aRtXwYz1",
    "first_name": "Max",
    "last_name": "Muster",
    "has_ownership": true,
    "ownership_percentage": 60.0,
    "has_control": true,
    "is_signer": true,
    "is_director": false,
    "role": "ceo"
  }
]

A PATCH that sends controllers replaces the whole list. Each person in it is matched to someone we already hold this way:

  1. With an id, it is that person. Their documents stay held under them, so you do not re-send them, and a corrected name keeps them.
  2. Without an id, it is the person we hold with the same first name, last name, and date of birth, when all three are present.
  3. Otherwise it is a new person, with a new id.

An id that is not a person on this customer, or the same id twice, returns 422 invalid_parameter with param: "controllers". A person you keep also keeps what their documents supplied wherever you send nothing. Send each id back to keep people stable across updates.

The customer object is the verification intake

Two intake-only arrays ride customer create and PATCH. We hold them for review, never as customer fields.

{
  "identifying_information": [
    {
      "kind": "passport",
      "issuing_country": "USA",
      "number": "P123456",
      "image_front": "<base64>",
      "image_back": "<base64, optional>"
    }
  ],
  "documents": [
    {"purpose": "selfie", "file": "<base64>"},
    {"purpose": "proof_of_address", "file": "<base64>"},
    {"purpose": "proof_of_tax_identification", "file": "<base64>"}
  ]
}
  • identifying_information[].kind: passport, id_card, drivers_license, or residence_permit. Optional: without it, the kind is read off the image at submit. When it cannot be read, the endorsement asks for it as id_document_kind.
  • identifying_information[].issuing_country is optional the same way: read off the image, and asked as issuing_country only when it cannot be.
  • identifying_information[].number is optional. Without it, the number is read off the image at submit.
  • A kind, issuing_country, or number you send wins over what the image reads.
  • documents[].purpose: selfie, proof_of_address, proof_of_tax_identification (a tax certificate or letter showing the taxpayer identification number), registration_document, articles_of_association (articles of incorporation or organization, bylaws, or a memorandum of association), operating_agreement (an LLC operating agreement, or a partnership or limited-partnership agreement), ownership_information, proof_of_signatory_authority (the list of the people authorized to represent or sign for the business), or other. What a review can ask for per risk or on request also has a purpose: proof_of_source_of_funds (either kind), and for a business evidence_of_good_standing, directors_registry (a certificate of incumbency), regulatory_license_registration, aml_policy, annual_report, proof_of_tax_exemption, and trade_name_registration. Which of these a customer owes depends on its kind and, for a business, its legal form. See Documents we ask for.
  • Images are base64, and data: URIs are accepted. Up to ten of each per request, and each file at most about 10 MB. A business's controller carries at most 4 identity documents and 4 documents.

Intake is strict. An unknown field on create or update is refused with 422 invalid_parameter naming it, never silently ignored. A file that is not valid base64 is 422 invalid_parameter too.

Due-diligence fields

A review can ask for the customer's economic profile, the same fields the industry takes flat on the customer. All are optional at creation and asked through missing when a review needs them. Send them as codes from these lists; a value outside the list for the customer's kind returns 422 invalid_parameter.

FieldKindValues
employment_statusindividualemployed, self_employed, retired, student, unemployed
occupationindividualA lowercase snake_case occupation code, such as software_developer
source_of_funds[]individualcompany_funds, ecommerce_reseller, gambling_proceeds, gifts, government_benefits, inheritance, investments_loans, pension_retirement, salary, sale_of_assets_real_estate, savings, someone_elses_funds
source_of_funds[]businessbusiness_loans, grants, inter_company_funds, investment_proceeds, legal_settlement, owners_capital, pension_retirement, sale_of_assets, sales_of_goods_and_services, third_party_funds, treasury_reserves
account_purpose[]individualcharitable_donations, ecommerce_retail_payments, investment_purposes, operating_a_company, other, payments_to_friends_or_family_abroad, personal_or_living_expenses, protect_wealth, purchase_goods_and_services, receive_payment_for_freelancing, receive_salary
account_purpose[]businesscharitable_donations, ecommerce_retail_payments, investment_purposes, other, payments_to_friends_or_family_abroad, payroll, personal_or_living_expenses, protect_wealth, purchase_goods_and_services, receive_payments_for_goods_and_services, tax_optimization, third_party_money_transmission, treasury_management
account_purpose_otherbusinessFree text, required when account_purpose includes other
expected_monthly_volume_usdeitherunder_5k, 5k_to_10k, 10k_to_50k, 50k_to_100k, 100k_to_1m, 1m_to_5m, 5m_to_10m, 10m_to_20m, over_20m
source_of_funds_descriptioneitherFree text
source_of_wealth[]businessaffiliate_or_royalty_income, asset_sales, business_dividends_or_profits, charitable_contributions, client_investor_contributions, gambling, inheritance, investments
source_of_wealth_descriptionbusinessFree text
estimated_annual_revenue_usdbusiness0_99999, 100000_999999, 1000000_9999999, 10000000_49999999, 50000000_249999999, 250000000_plus
expected_monthly_payments_usdbusinessA whole USD amount
ownership_structurebusinessbearer_shares_or_undisclosed_nominee_arrangement, fund, majority_owned_subsidiary_of_fi_or_nbfi, majority_owned_subsidiary_of_publicly_listed_company, owned_by_trust, privately_owned, publicly_listed_company, wholly_owned_subsidiary_of_fi_or_nbfi, wholly_owned_subsidiary_of_publicly_listed_company
business_industry[]businessNAICS codes, 2 to 6 digits
physical_addressbusinessThe operating address, when it differs from the registered one
is_politically_exposed, is_us_tax_person, is_us_citizen, is_funds_ownereitherBooleans

Nothing here enters review on its own. We hold documents until the customer's first submission, POST /api/customers/{customer_id}/verifications. After it, a PATCH that changes something resubmits by itself. See Verification & Endorsements.

Requesting endorsements

Enrollment is explicit. A customer is reviewed only for the endorsements you name, and that review is its verification.

{"endorsements": ["endo_usd"]}

Requesting endo_usd needs contact fields no document can supply, already on the customer or sent in the same request. For an individual that is email and phone. For a business it is email. Missing ones return 422 endorsement_profile_required naming them, in sandbox as well as live. You can request endorsements later with a PATCH.

Tax data is not needed to request endo_usd, but the review needs it, so send tax_id, and tax_residence_country for an individual, on create. In live, until they arrive, the endorsement lists them in missing and the first submit returns 422 verification_incomplete naming them.

Reading a customer

{
  "id": "cus_033y1FhTOmoW9W2jAuSvQx",
  "object": "customer",
  "kind": "individual",
  "first_name": "Ana",
  "middle_name": null,
  "last_name": "Silva",
  "email": "ana@example.com",
  "address": {"state": "CA", "country": "US"},
  "status": "active",
  "tos": {
    "status": "accepted",
    "tos_version": "2026-08-01",
    "accepted_at": "2026-08-26T09:14:40+00:00"
  },
  "endorsements": [
    {
      "name": "endo_usd",
      "status": "approved",
      "requirements": {
        "complete": ["compliance_review", "identity", "proof_of_address", "selfie", "terms_of_service"],
        "uploaded": [],
        "pending": [],
        "missing": [],
        "issues": []
      }
    }
  ],
  "partner_reference_id": "user-8213",
  "created_at": "2026-08-26T09:14:40+00:00"
}
  • endorsements is the verification reading. One entry per endorsement we offer (endo_usd today). One you have not requested reads incomplete with compliance_review in missing. Its status is the gate, and its requirements buckets show each item's state as a bare documented code.
  • status is the account itself: pending, active, rejected, or frozen (set by Rasto; contact support). See Statuses & Lifecycles.

The payload is deliberately lean. Identity inputs you send (date of birth, phone, documents, tax data) go to review and are never echoed back, and the address trims to state and country. A business's controllers list only each person's id, names, and roles. A business payload also carries trade_name and business_description. Keep your own copy: the API reflects readiness, not the dossier.

Updating

PATCH /api/customers/{customer_id} updates identity fields and accepts the same two document arrays. Supplying what a missing or issues bucket asks for is an ordinary PATCH. After the customer's first submission, a PATCH that changes something resubmits by itself, and one that changes nothing does nothing.

Two PATCH semantics to know:

  • Nested objects merge. {"address": {"state": "NY"}} fixes the state alone. Sending the whole object replaces every line it names, and "address": null clears it.
  • Reading never overwrites a value you sent. At submit, the documents fill only the fields left empty, or ones an earlier document filled, for an individual, a business, and each of its controllers. A value you supplied changes only through your own PATCH.

Set partner_reference_id to your own user id at creation. It is unique per environment within your account, filterable on list endpoints, and the simplest way to join Rasto records to yours. A collision returns 409 partner_reference_id_exists.