Skip to content

Onboarding Businesses

Onboarding a business means completing KYB. Unlike an individual application, which is a single object you fill in and submit, a business application is a tree: the business itself, one or more related parties, and a set of document requests that Jiko derives from what you tell it. You submit once, when the whole tree is complete.

When the application reaches APPROVED, Jiko creates a customer, and the application's customer_id is populated. That customer can then hold pockets.

Prerequisites

Feature flags

Feature flags are set by Jiko per partner and evaluated against the API user making the request. A call that needs a flag you do not have fails with 403. Ask your Jiko point of contact for the ones you need.

FlagNeeded forWithout it
non_us_id_citizenshipsSubmitting INTERNATIONAL_ID identification on a related party. A comma-separated list of ISO 3166-1 alpha-2 citizenship codes; a non-empty list enables the feature, empty or absent disables it403 where your partnership has no allowlist at all, and 422 where it has one but the related party's citizenship is not on it

Nothing else about business onboarding is flag-gated. POST /api/v1/business-applications/ and the rest of the tree are available to every partner.

Everything else

  • The Partner Obligations discharged before you start. Verify ownership of the phone number and the email address on the application, and display Jiko's agreements — fetched from GET /api/v1/agreements/ — recording the version shown and the timestamp of consent. Re-fetch for every new application; the current version changes, and consent against a stale version is not consent to what Jiko is obliged to have shown. None of this is checked by the API.
  • API credentials for the environment you are calling. Build against sandbox first: a business application is a tree assembled over several calls, and the document list moves as you fill it in. The sandbox status simulator makes every terminal state reachable in seconds.
  • A way to upload PNGs. Document uploads require a Content-Type of image/png; anything else is rejected at the header. Convert before you upload.
  • Exactly one related party carrying CONTROL_PERSON. None is CONTROL_PRONG_MISSING at submission; more than one is MULTIPLE_CONTROL_PRONGS. Both block submission outright.
  • Ownership percentages that add up. Each related party's ownership_percentage is a string parseable to a number between 0 and 1 — "0.51" is 51% — and the percentages across active beneficial owners cannot total more than 100%.
  • agreement_consent given by a control person or authorized representative. The API does not check this — agreement_consent carries only a version and a timestamp, with no signer field — so enforce it in your own UI and record on your side who accepted.
  • A complete risk_info block before you read the document list. Document requests are derived from the entity type, the industry, the risk categories and the related parties. Read the list thin and it changes under you.
  • Every derived document request uploaded and not INVALID. An INVALID document does not fail the application, but the application will not move until it is replaced.
  • A path for answering RFIs. There is no webhook for an RFI. An application sitting in MANUAL_REVIEW with an open RFI is waiting on you, and it waits silently.
  • A webhook subscription for application.approved, application.manual_review, application.documents_needed and application.rejected. The payload is application_id only, so each event means "fetch the application" — including the approval, which is the only place customer_id appears. Subscriptions are recorded against the API user that creates them.

The shape of the flow

  1. Create the business application. POST /api/v1/business-applications/
  2. Add related parties. Every control person and authorized representative gets their own application.
  3. Read the document requests. Jiko derives them from the entity type and the risk answers — you cannot know them up front.
  4. Upload each document.
  5. Submit. POST /api/v1/business-applications/{application_id}/apply/
  6. Respond to RFIs, if Jiko's review raises any.
  7. Wait for a terminal status, delivered by webhook.

Steps 1–4 are incremental. The application starts in CREATED and every field is optional on the create call, so you can build it up over repeated PATCH /api/v1/business-applications/{application_id}/ calls as your own UI collects the data. Validation of completeness happens at submission, not at creation. Related parties can be updated and deleted the same way, right up until you submit.

Step 4 is a loop. Supplying the last outstanding document does not resume the review: the application moves from DOCUMENTS_NEEDED to PENDING, which means "nothing is outstanding, and Jiko is waiting for you to resubmit". You call apply again. An application parked in PENDING is waiting on you, and no webhook will say so.

Relevant API endpoints

StepPurposeEndpoint
1Fetch the agreements to displayGET /api/v1/agreements/
2Create the business applicationPOST /api/v1/business-applications/
3Add fields incrementally as your UI collects themPATCH /api/v1/business-applications/{application_id}/
4Add a related partyPOST /api/v1/business-applications/{application_id}/related-party-applications/
5Correct or remove a related party before submissionPATCH / DELETE /api/v1/business-applications/{application_id}/related-party-applications/{related_party_application_id}/
6Read the derived document checklistGET /api/v1/business-applications/{application_id}/documents/
7Upload a document (Content-Type: image/png)POST /api/v1/documents/{document_id}/
8Submit, and resubmit after a DOCUMENTS_NEEDED roundPOST /api/v1/business-applications/{application_id}/apply/
9Read the status and, on approval, customer_idGET /api/v1/business-applications/{application_id}/

Create the business application

POST /api/v1/business-applications/
FieldNotes
idOptional client-supplied UUID
nameLegal name
entity_typeSOLE_PROPRIETOR, CORPORATE, LLC, PARTNERSHIP, INCORPORATED_ASSOCIATION, UNINCORPORATED_ASSOCIATION, NON_BANK_FINANCIAL_INSTITUTION, NON_PROFIT, TRUST and others
doing_business_asDBA name, where it differs from the legal name
identification_numberEIN or equivalent
addressISO-format address
website
contactBusiness contact — name, email, phone
formation_date
industryAn industry code, plus other_industry free text when the code is "other"
risk_infoSee below
agreement_consentConsent to Jiko's agreements. See Who may consent to the agreements

risk_info drives the rest of the application

This block is what determines which documents Jiko asks for and whether the application routes to manual review. Fill it in properly and the document list settles early; leave it thin and the list changes under you.

These are always required: business_activity_location, account_usage, monthly_transactions, first_month_deposit, source_of_funds, annual_revenue and company_mission.

These become required depending on what else you sent:

WhenAlso required
risk_categories contains CRYPTOCURRENCYhas_current_enforcement_actions
risk_categories contains FINANCIAL_OR_MONEY_MOVEMENThas_current_enforcement_actions and primary_regulator
source_of_funds is CLIENT_OR_EXTERNAL_FUNDSsource_of_funds_explanation

primary_regulator is a free-text string in the API, but the answers Jiko expects are a short set: FRB, OCC, FDIC, FINRA, CFTC, FinCEN (MSB registration), State regulatory agency, Other. Offer those rather than an open box.

FieldValues
risk_categoriesINTERNET_GAMBLING, CANNABIS, CRYPTOCURRENCY, CROWDFUNDING, FINANCIAL_OR_MONEY_MOVEMENT, NON_US_ENTITY, FINTECH_OR_BAAS
company_missionFree text
has_current_enforcement_actionsBoolean
primary_regulatorFree text; see the accepted answers above
business_activity_locationPRIMARILY_US, MIX_OF_US_AND_NON_US, PRIMARILY_NON_US
source_of_fundsINTERNAL_FUNDS, CLIENT_OR_EXTERNAL_FUNDS, CRYPTOCURRENCY_EXCESS_RESERVES and others, with source_of_funds_explanation
account_usageMONEY_STORAGE, MONEY_STORAGE_US_BANKS, MONEY_STORAGE_NON_US_BANKS, CRYPTOCURRENCY_EXCESS_RESERVES and others
annual_revenueBanded, for example PRE_REVENUE
monthly_transactionsBanded
first_month_depositBanded
is_finra_registered_broker_dealerBoolean

Declaring CRYPTOCURRENCY as a risk category, for instance, pulls in a distinct set of document requests — legal analysis of the business model, coins and tokens listed, coin rating policy, blockchain analytics used, market manipulation policy, BSA/AML/OFAC policies, independent AML audit report, internal risk assessment. Those requests do not appear until the category is declared.

POST /api/v1/business-applications/{application_id}/related-party-applications/
GET  /api/v1/business-applications/{application_id}/related-party-applications/
GET  /api/v1/business-applications/{application_id}/related-party-applications/{related_party_application_id}/
FieldNotes
name
addressISO-format address
date_of_birth
identification_numberSSN, passport, TIN, driver's license or international ID. Returned masked
phone_numberE.164
email
titleTheir role in the business, free text
rolesCONTROL_PERSON and/or AUTHORIZED_REPRESENTATIVE — the only two values the API accepts
ownership_percentageA string parseable to a number between 0 and 1. "0.51" is 51%
citizenshipISO 3166 country code

address.state is required only when address.country is US.

There are only two roles, so a beneficial owner or a member of senior management who is neither the control person nor an authorized representative is still registered as a related party — recorded through title and ownership_percentage rather than through a role of their own.

The identification number is masked, and that is a trap on update

identification_number comes back masked on every read — *****6789. There is no way to read the real value back.

The consequence: do not echo it into a PATCH. An update that sends the object you just fetched will write the mask over the real number, and the application then carries *****6789 as the related party's identification. Send only the fields you are actually changing.

Exactly one related party must carry CONTROL_PERSON. Submitting with none, or with more than one, is rejected — the submission exception reasons are explicit about this: CONTROL_PRONG_MISSING and MULTIPLE_CONTROL_PRONGS.

The agreement_consent on the business application may only be given by a related party holding the CONTROL_PERSON or AUTHORIZED_REPRESENTATIVE role.

The API does not check this. agreement_consent carries only a version and a timestamp — there is no signer field, and submission does not compare the consent against the related parties. Enforce it in your own UI: present the agreements only to a party carrying one of those roles, and record on your side who accepted them.

Non-US identification

INTERNATIONAL_ID is accepted as an identification type for a related party only where the party's citizenship is on your partnership's allowlist. Outside that allowlist, an international ID is rejected at validation. If you onboard non-US control persons, confirm the allowlist with your Jiko point of contact before building the form.

Document requests

GET /api/v1/business-applications/{application_id}/documents/

Document requests are derived, not chosen. They depend on the entity type, the industry, the risk categories and the related parties you have entered, so the list is only meaningful once the rest of the application is filled in. Read it, do not hard-code it.

The set spans entity-formation documents (ARTICLES_OF_INCORPORATION, OPERATING_AGREEMENT, PARTNERSHIP_AGREEMENT, BYLAWS, ARTICLES_OF_ORGANIZATION, CORPORATE_CHARTER, TRUST_FORMATION_RECORDS, LIST_OF_TRUSTEES, TRUST_VERIFICATION_DOCUMENT, PROOF_OF_501_STATUS, CERTIFICATE_OF_GOOD_STANDING), identity documents for related parties (ID_FRONT, ID_BACK, PASSPORT, SELFIE, ADDRESS_VERIFICATION, IDENTIFICATION_NUMBER_VERIFICATION), financial documents (BANK_STATEMENTS_1–3, FLOW_OF_FUNDS, EIN_CONFIRMATION, ORG_CHART, BUSINESS_DESCRIPTION) and the risk-driven policy documents above.

Upload against the document's own ID:

POST /api/v1/documents/{document_id}/

Uploads must carry Content-Type: image/png. The header is pattern-matched, so a JPEG or a PDF is rejected before the file is read — worth knowing early, because most of what a business will hand you is a PDF.

Each document carries a status: PENDING_UPLOAD → PENDING_REVIEW → APPROVED or INVALID. An INVALID document needs to be re-uploaded; it does not fail the application on its own, and it carries an exception_reason saying what was wrong with it. Surface that to whoever is uploading.

You do not have to wait for review to finish before submitting. The bar is that every request is APPROVED or PENDING_REVIEW — that is, nothing is still PENDING_UPLOAD or INVALID.

One set of requests is an either/or. Where INTERNAL_KYC_AUDIT, EXTERNAL_KYC_AUDIT and KYC_POLICIES_AND_PROCEDURES are all requested, the business satisfies them with either EXTERNAL_KYC_AUDIT on its own, or INTERNAL_KYC_AUDIT together with KYC_POLICIES_AND_PROCEDURES. A UI that insists on all three will block a business that has done nothing wrong.

Submit

POST /api/v1/business-applications/{application_id}/apply/

Submit only when the business application, every related party application and every document request are complete. If anything is missing, the response tells you exactly what, via exception_reasons:

NAME_MISSING, DATE_OF_BIRTH_MISSING, ADDRESS_MISSING, PHONE_NUMBER_MISSING, EMAIL_MISSING, AGREEMENT_CONSENT_MISSING, ENTITY_TYPE_MISSING, FORMATION_DATE_MISSING, INDUSTRY_MISSING, OTHER_INDUSTRY_MISSING, BUSINESS_CONTACT_MISSING, RISK_PROFILE_MISSING, RISK_CATEGORY_MISSING, COMPANY_MISSION_MISSING, ACCOUNT_USAGE_MISSING, PRIMARY_REGULATOR_MISSING, SOURCE_OF_FUNDS_MISSING, RELATED_PARTIES_INCOMPLETE, CONTROL_PRONG_MISSING, MULTIPLE_CONTROL_PRONGS, CITIZENSHIP_MISSING, ROLES_MISSING.

Surface these to whoever is filling in your form. They map one-to-one onto fields.

Lifecycle

StatusMeaningWho it is waiting on
CREATEDBeing filled in. Not yet submittedYou
SUBMITTEDSubmitted, under evaluationJiko
DOCUMENTS_NEEDEDJiko needs more documents. Read the checklist and uploadYou
PENDINGEvery outstanding document has been supplied. Call apply againYou
MANUAL_REVIEWUnder human review at JikoJiko
APPROVEDKYB passed. A customer now exists; read customer_id. Terminal—
REJECTEDKYB failed. Terminal—
CLOSEDClosed for inactivity. Terminal—

PENDING is the one to read carefully. It does not mean "in processing" — it is where an application lands once you have cleared the document requests, and it moves no further until you resubmit. CLOSED is worth designing for too: an application that nobody finishes does not sit in CREATED forever.

Sandbox testing

In sandbox the business's identification_number — the EIN — decides the outcome, so every status is reachable without real KYB. The first digit controls what happens on the first apply:

PrefixStatus after apply
2DOCUMENTS_NEEDED
4APPROVED
5REJECTED
Anything elseMANUAL_REVIEW

A 2 behaves differently on the way back than the individual path does. Once you have uploaded the requested documents and applied again, a business application goes to MANUAL_REVIEW — not to APPROVED. To reach an approved business customer in sandbox, start from a 4.

Sandbox appends a unique suffix to the identification number you submit, so the same EIN can be reused across applications without colliding. The number you read back is therefore not the one you sent.

Requests for information (RFIs)

Where review needs something a document request cannot express, Jiko opens an RFI — a message thread on the application.

GET  /api/v1/business-applications/{application_id}/rfis/
GET  /api/v1/business-applications/{application_id}/rfis/{rfi_id}/
POST /api/v1/business-applications/{application_id}/rfis/{rfi_id}/messages/
POST /api/v1/business-applications/{application_id}/rfi-messages/{message_id}/documents/
GET  /api/v1/business-applications/{application_id}/rfi-messages/{message_id}/documents/{document_id}/

An RFI moves through CREATED → REQUESTED → ANSWERED → APPROVED or REJECTED, and can be CANCELED. Messages are typed OPS (from Jiko) or CUSTOMER (from you), and a message can carry documents.

An application sitting in MANUAL_REVIEW with an open RFI is waiting on you, not on Jiko. Poll the RFI list, or surface the thread into your own support tooling, or the application stalls silently.

Webhooks

EventMeaning
application.approvedKYB passed; a customer exists
application.manual_reviewRouted to human review
application.documents_neededMore documents required
application.rejectedKYB failed

Payload: application_id. Fetch the application to learn what changed and, on approval, to read customer_id.

There is no event for an RFI. RFIs must be polled.

After approval

The application's customer_id is the handle for everything downstream:

GET  /api/v1/customers/{customer_id}/
POST /api/v2/customers/{customer_id}/pockets/
GET  /api/v2/customers/{customer_id}/pockets/

An approved customer does not necessarily have a pocket

For most partnerships, approval creates the customer and nothing else. Opening a pocket is a call you make.

Automatic pocket-and-portal creation at approval does exist, but it is a legacy behavior limited to an explicit allowlist of partner IDs held in Jiko's configuration. If your partnership is on that list, an approved customer already has a pocket and a virtual bank account portal with a routing and account number. If it is not, GET /api/v2/customers/{customer_id}/pockets/ comes back empty and stays empty until you create one. Ask your Jiko point of contact which case applies, and read the pocket list rather than assuming either answer.

A customer may hold up to 20 pockets per partner by default. The limit counts every pocket ever created for that customer, including closed ones — closing a pocket does not free a slot. Create pockets for durable purposes; do not use them as per-transaction or per-invoice containers. Portals, which are uncapped on the bank rails, are the right tool for that.

Endpoints

OperationEndpoint
List agreements to displayGET /api/v1/agreements/
Create a business applicationPOST /api/v1/business-applications/
Get a business applicationGET /api/v1/business-applications/{application_id}/
Update a business applicationPATCH /api/v1/business-applications/{application_id}/
Create a related party applicationPOST /api/v1/business-applications/{application_id}/related-party-applications/
List related party applicationsGET /api/v1/business-applications/{application_id}/related-party-applications/
Get a related party applicationGET /api/v1/business-applications/{application_id}/related-party-applications/{related_party_application_id}/
Update a related party applicationPATCH /api/v1/business-applications/{application_id}/related-party-applications/{related_party_application_id}/
Delete a related party applicationDELETE /api/v1/business-applications/{application_id}/related-party-applications/{related_party_application_id}/
List document requestsGET /api/v1/business-applications/{application_id}/documents/
Upload a documentPOST /api/v1/documents/{document_id}/
SubmitPOST /api/v1/business-applications/{application_id}/apply/
List / get RFIsGET /api/v1/business-applications/{application_id}/rfis/
Reply to an RFIPOST /api/v1/business-applications/{application_id}/rfis/{rfi_id}/messages/

See also