next_step object that tells you what’s outstanding, so you don’t infer it from
status.
This is self-serve onboarding for entities your key owns. The key’s user is
the creator and admin. The user is not added as a representative automatically.
If this user is the business signer, add the user as the primary representative
in step 3. To onboard entities on behalf of your customers as a platform, use
Partner Onboarding instead.
You’ll need
- A global API key (user-scoped, not entity-scoped) with the
entity:createscope for writes andaccounts:readto read and list onboarding state. Onboarding routes reject entity-scoped keys with403. - No
x-entity-idheader. The entity is addressed in the URL path.
Testing through the development API. The examples below use
https://api.dev.meow.com/v1. This environment also exposes the
approval simulation that stands in
for compliance review, so you can drive an application all the way to
approved and open a simulated checking account. Non-production keys are granted
the simulations:write scope automatically.Read next_step after every call
Every onboarding read returns a next_step. For a US entity mid-onboarding it
looks like this:
The loop: call an endpoint, then
GET /entities/{entity_id}, act on
next_step.step, repeat until can_submit is true, then submit.
Some entities draw an extra due-diligence step (
complete_due_diligence) before
they can submit. Forms that collect plain data are submittable through the
due-diligence endpoints; forms that require
document uploads must be finished in the Meow dashboard. A follow-up
information request after submission (resolve_info_requests) is answered
through the API. Read next_step.info_requests[] for the request_id, then
fetch the form,
upload each document
and answer the questions.1. Create the entity
POST /entities creates the entity and returns its public ID. The creating user
is granted admin, so the same key can act on the entity immediately. Send an
empty body to create a bare entity, or seed any KYB business details up front.
Response
id. It’s the {entity_id} for every call below, and the x-entity-id
header once the entity is onboarded and you call entity-scoped APIs.
legal_structure is one of: ccorp, corp, scorp, llc, llp, lp,
partnership, soleprop, nonprofit, trust, estate, foreign_entity,
scheme.
International businesses
Meow onboards businesses in 44 countries, not just the US. The flow is identical to the walkthrough here; only a few fields differ for a business incorporated outside the US.Supported countries (ISO 3166-1 alpha-2): AD, AT, AU, BE, BM, BS, CA, CH, CL, CZ,
DE, DK, ES, FR, GB, GG, GR, HR, IE, IS, IT, JE, JP, KR, LT, LU, MC, MU, NL,
NO, NZ, OM, PL, PR, PT, SE, SG, SI, SK, SM, TW, US, UY, VG. A
business_address.country outside this set is rejected at write time with a
400 that lists every supported country.incorporation_state: omit it. It’s the US state of incorporation and applies to US entities only.business_taxid: send the local registration or tax number instead of an EIN (a UEN in Singapore, a UTR in the UK, a BN in Canada, and so on).legal_structure: useforeign_entity.business_address.country: the ISO code of a supported country. A state or province and a postal code are still required where the country uses them.
- Documents:
next_step.required_proof_typesfor a non-US business is typically["incorporation", "shareholder_registry", "officer_registry"]: the certificate of incorporation, the shareholder registry, and the register of directors. These apply to every non-US country. The US-onlyaddressproof is not requested. - Representative KYC: pass each representative’s country-specific
id_typeandid_number(for examplesg_nric,au_passport,ca_sin) instead ofus_ssn. See Verify each representative. - Submission: choose
grasshopperas thebanking_account_product_type. Grasshopper Bank is Meow’s preferred checking-account provider.crbis available only to US entities. Every other supported country usesgrasshopper.
next_step loop, representatives, documents and submission,
works exactly as described below.
2. Update business details
PATCH /entities/{entity_id}/business-details fills in or corrects KYB details
before the application is submitted. Send only the fields you want to change;
anything you omit keeps its current value. Use it for the business profile the
create call didn’t include, and to answer the account-purpose and
digital-currency questions (collect_additional_details).
next_step. Send physical_address together with business_address; omitting
it keeps any physical address already on file, or uses the legal address when
none is set.
3. Add representatives
POST /entities/{entity_id}/representatives records a beneficial owner or
officer and returns its representative_id. This step is create-only.
Verify the representative separately (section 4).
Mark exactly one representative as the signer with is_primary: true; setting it
demotes any previous primary. A primary representative is required before the
application can be submitted.
To promote a representative already on file, call
POST /entities/{entity_id}/representatives/{representative_id}/make-primary.
It makes that representative the signer and demotes the current one. Allowed
until the application is submitted.
Response
title_idis one of:chief executive officer,chief financial officer,chief operating officer,chief administrative officer,president,general partner,managing member,finance manager.percent_ownershipis required whenis_beneficial_owneristrue, between25and100. Total beneficial ownership across representatives cannot exceed100.- Each
emailis unique per entity. Re-posting the same address returns400.
4. Verify each representative
KYC is per representative, with two ways to do it. Pick one per person.- You hold their details
- They self-verify
Submit the representative’s identity data and Meow runs verification on it.For
Response
id_type: us_ssn send nine digits with or without dashes
(123-45-6789 or 123456789); for us_ssn_last_4 send the last four.ip is required: the end user’s IPv4 or IPv6 address, forwarded to the
verification provider as a fraud signal.Sandbox testing. In sandbox and dev the verification provider only clears a
known test identity, so use Leslie Knope below. The reliable path is the
self-verify link (the “They self-verify” tab): mint the link and complete the
flow with these exact details. A representative’s
kyc_status must reach
approved before the application can be
approved. Poll the representatives
array to confirm.next_step advances once every
representative has started verification, not once they pass, so track the
actual outcome per representative via their kyc_status in the representatives
array on the onboarding status, or the
identity_verification.* webhooks. A representative’s kyc_status matches the
webhook stream; action_required means that person needs another step (for
example, a document). Mint a verification link and share it so they can finish.
The top-level kyc_status reflects the primary representative.
5. Upload supporting documents
next_step.required_proof_types lists exactly which documents the entity still
owes. For a US entity that is ["incorporation"]. Each one uses a three-step
flow: get a pre-signed URL, PUT the bytes, then confirm. Repeat the flow for
each proof type:
1
Request an upload URL
Response
2
PUT the file to upload_url
Content-Type you requested, keep the file under max_bytes, and
upload before the URL expires.3
Confirm the upload
Response
4
Repeat for the proof of physical address
required_proof_types as the proof_type. Before
submission a US entity is asked for incorporation. A reviewer can ask for
more after submission, and address is the common one: it is proof of
physical address at the entity level, such as a utility bill, bank
statement, or lease agreement evidencing the entity’s relationship to its
physical address. Those arrive as an information request, which
next_step.info_requests[] reports with the request_id to upload against.
Other common values include articles_of_organization, bylaws, operating_agreement,
ein, bank_statement, and beneficial_owner_id.
Documents for international businesses
A non-US entity’srequired_proof_types usually includes two registry
documents alongside incorporation. These prove who owns and who runs the
company, the things US entities establish through their EIN and representative
data instead.
Whatever the country, upload only the values that appear in
next_step.required_proof_types. That list is the source of truth for what a
given entity owes. Meow may request further documents during review; those
arrive as their own requirements.
Address documents uploaded for a representative do not satisfy the
entity-level
address requirement: the document must evidence the
entity’s physical address. next_step.can_submit stays false until every
proof type in required_proof_types has been uploaded.Complete required due diligence
Some industries draw an extra enhanced due diligence (EDD) step before the application can be submitted. When one applies,next_step.step is
complete_due_diligence. List the required forms, then for each form that’s
submittable through the API, fetch its schema and submit it. Forms that collect
document uploads can’t be submitted through the API (requires_webapp: true) and
must be completed in the Meow dashboard.
1
List the required forms
GET /entities/{entity_id}/due-diligence returns each required form with its
completion status and whether it must be finished in the web app.Response
2
Fetch a submittable form's schema
GET /entities/{entity_id}/due-diligence/schema/{form_type} returns the form’s
pages and fields, including types, choices, validation, and conditional visibility, so
you can build a valid submission. Only forms submittable through the API have a
schema.3
Submit the completed form
POST /entities/{entity_id}/due-diligence submits one form. Set form_type to
the form you’re answering; form_data matches that form’s schema. The response
is the refreshed onboarding status.complete, and any
requires_webapp forms are finished in the dashboard, next_step advances past
complete_due_diligence and can_submit can turn true.
6. Submit the application
Oncenext_step.can_submit is true, submit the application with
POST /entities/{entity_id}/submit. Choose the checking account product to open.
If anything is still outstanding, this returns 400 with the remaining
requirements; check next_step.can_submit first.
Use grasshopper for the preferred Grasshopper Bank checking account. Add
stablecoins to product_features when the business also needs USDC access.
Omit product_features when the business needs checking only.
Response
missing lists everything outstanding across
both, and info_requests[] carries the per-request detail. Poll this endpoint,
or subscribe to the info_request.* webhooks, and act on each as it appears.
The agreements
Outstanding agreements appear inmissing, and consent_url is where the
primary representative accepts them. Share the link. Anyone who holds it can
accept for the business, so treat it as a secret.
consent on the same response gives the detail: remaining_items is what is
left, and status moves pending → viewed → completed.
Submitting emits onboarding_consent.updated with status: "pending" and the
full remaining_items, so a caller watching the event stream is told the
agreements are owed without polling. Later events fire as the representative
opens the form and accepts each item.
While any agreement is outstanding, POST /accounts returns 403. The review
still runs. Once the representative accepts everything, they leave missing.
Requested products also wait for their agreements. Before you simulate approval,
open consent_url. Then wait until consent.status is completed. If you skip
this step, checking can open while a requested product remains pending.
Information requests
Each entry innext_step.info_requests[] is a reviewer asking for something.
note carries their message. One request can ask for documents, questions, or
both, and one schema describes all of it.
1
Fetch the form
Response
file_upload element is a document. Its file_upload_config.proof_type is
the value to pass to the upload endpoints, and accepted_types is what the
file may be. Every other element is a question.2
Upload each document
Use the request-scoped upload endpoints. The pre-submission
/documents/upload-url pair is closed once you submit, and it cannot attribute
a file to a request.Confirm response
request_completed is false because the questions are still open.3
Answer the questions
Post the answers keyed by the element
name from the schema. This submits
them, so send them complete. There is no draft state on this API.Response
next_step.info_requests[]. With
nothing else outstanding, step returns to monitor_review.
A request can expire.
next_step.info_requests[] carries expires_at
alongside request_id, required_proof_types, questions_pending, and the
reviewer’s note. Uploads against an expired or completed request are
rejected, and the request stops appearing in the list.Reaching approved
status leaves under_review when the bank finishes, not when you clear
these:
approved: the business application is approved and its checking account is active.submitted: KYB passed and the account is still opening.rejected: the application was declined.
application.* webhooks, or by polling
GET /entities/{entity_id}.
approved does not mean the queue is empty. Approval does not wait on the
agreements, so an approved business can still owe them, and an information
request raised before approval stays open after it.
approved also does not mean that every requested product is ready. Stablecoin
access has separate approval and account-creation steps. Do not run the
stablecoin funding simulation
until the stablecoin financial account exists.
next_step.step keeps naming the work while any is left, so it never
contradicts missing: an approved business that still owes its agreements
reads accept_terms, and one with an open request reads
resolve_info_requests. step becomes onboarding_complete only once
missing and info_requests[] are both empty. A rejected application owes
nothing, so it reports onboarding_complete immediately.
Sandbox: simulate application approval
In sandbox and development environments there is no human compliance review, so a submitted application would otherwise sit inunder_review forever. Simulate
the approval with
POST /simulations/entities/{entity_id}/application_approval. It approves the
application as if compliance review had passed. It also approves each requested
product feature and starts checking-account onboarding.
- Every representative’s
kyc_statusmust beapprovedfirst. Real review never approves an application whose beneficial owner failed KYC, and neither does the simulation: it returns400and names how many representatives still need to pass. PollGET /entities/{entity_id}and confirm every entry in therepresentativesarray showskyc_status: "approved"before calling this. In sandbox, get there with the verification link and the test identity. - The application must already be submitted (section 6).
- Complete the agreements at
consent_urlbefore this call when the application requests another product. Otherwise, checking can open while that product remains pending. - The body is optional.
banking_account_product_typedefaults tograsshopper, Meow’s preferred provider.crbis also supported for eligible businesses. - Use an entity API key scoped to the target entity, or a global (user) API key with the
simulations:writescope (granted automatically on non-production keys); for the global key, the key’s user must be an admin of the entity.
status moves to submitted immediately
and to approved once the checking account activates. Poll
GET /entities/{entity_id} or subscribe to the application.* webhook events
to observe the transition.
Requested stablecoin onboarding continues asynchronously after the Grasshopper
account opens. The simulation approves the request, but it does not make the
stablecoin financial account available in the same response.
The call is safe to repeat. If account opening stalls in the sandbox (the
status sits at submitted for more than a few minutes), call it again. A
retry completes the stalled opening and adopts the account the sandbox bank
already created, without opening a duplicate.
7. Track progress to submission
GET /entities/{entity_id} returns the lifecycle status, uploaded
documents, next_step, and a representatives array with each
representative’s kyc_status. The top-level kyc_status reflects the primary
representative.
Response
8. List your entities
GET /entities returns every entity your key’s user owns, each tagged with its
onboarding_type, with opaque-offset pagination.
Response
page is non-null, pass page.nextOffset as the offset query parameter
for the next page. When page is null, you’ve reached the end.
Track updates with webhooks
Instead of pollingGET /entities/{entity_id}, subscribe once and let Meow push
each change. A global key’s own onboarding events, identity_verification.*
for KYC outcomes and application.* for KYB lifecycle changes, deliver to a
regular webhook subscription, so the same key you onboard with can receive them.
signing_secret from the response. It is returned once. Omit
event_types (or send null) to receive every event the key can see. Each
delivery carries the same status values you would otherwise poll for, so you
can drive the whole flow off the stream. The key needs the webhooks:write and
webhooks:read scopes, and the url must be public HTTPS. See the
webhooks guide for signature verification, retries, and
out-of-order handling.
End to end
See also
Create an entity
Full request contract for
POST /entities.Update business details
Fill in or correct KYB details before submission.
Add a representative
Beneficial owners and officers, with the primary signer flag.
Submit the application
Choose the account product, then send for review.