Onboard a company
A merchant's legal information is represented in Rootline as a company. A company can own one or multiple accounts.
This page covers how you onboard a merchant: how you create its company, redirect the merchant to a personalized onboarding link, and track verification through to approval. Accounts are covered on the next page.
Overview
You onboard a merchant by pre-creating its company through the Config API. In return you receive a company-specific onboarding link, which you redirect the merchant to. Because you create the company before the merchant does anything, you hold its id from the start.
The Config API base URL is https://config-api.rootline.com (use https://config-api.staging.rootline.com for staging).
Always test the onboarding flow end-to-end on staging first. Production is the live onboarding flow: every company you submit there is reviewed by Rootline's operations team and there are no test parameters or test modes.
The company object
The company is the merchant's legal entity. When you create it, it holds only the data you provide. The rest (legal identity, UBOs, bank accounts, capabilities) is collected from the merchant during onboarding.
{
"id": "co_8f3a2b1c",
"object": "company",
"created_at": "2026-06-24T10:30:00Z",
"legal_name": "Coffee Corner B.V.",
"trade_name": "Coffee Corner",
"description": "Specialty coffee bar in Amsterdam",
"address": {
"street_address": "Prinsengracht 449",
"postal_code": "1016HN",
"city": "Amsterdam",
"country": "NL"
},
"reference": "partner-internal-id-42",
"verification_status": "created",
"next_action": {
"type": "provide_information",
"onboarding_url": "https://onboarding.rootline.com/roasters.com/companies/co_8f3a2b1c"
}
}
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the company, prefixed co_. |
object | string | Always company. |
legal_name | string | The legal name of the company. |
trade_name | string | The public-facing name, or "doing business as" (DBA) name. |
description | string | A description of the company. |
address | object | The company's address. Fields: street_address, street_address2, postal_code, city, state, country (ISO 3166-1 alpha-2). |
reference | string | Your own reference to identify the company (e.g. your internal ID). |
verification_status | string | Where the company sits in the verification lifecycle: created, open, verified, not_accepted, or suspended. See Verification status lifecycle. |
next_action | object | What needs to happen next for the company to move forward, including the onboarding link when one is required. See Next action. |
created_at | string | When the company was created. |
Verification status lifecycle
| Status | Meaning |
|---|---|
created | You created the company through the API, but the merchant has not yet submitted the onboarding form or accepted Terms of Service. Only the data from your POST /v1/companies call exists. |
open | The merchant has submitted the onboarding form and accepted ToS. Verification and assessment are in progress. Check next_action for any further detail on what is expected from the merchant. |
verified | The merchant passed all verification checks and is approved to transact. |
not_accepted | Final rejection. The merchant will not be onboarded (e.g. prohibited business, failed KYC). Terminal. |
suspended | Non-response (never verified), duplicate or stale onboarding, or a previously verified merchant that failed Enhanced Due Diligence or Periodic Review. Only you can request reactivation. |
┌─────────────┐
POST ──────►│ created │
└──────┬──────┘
│ merchant submits form, accepts ToS
▼
┌─────────────┐◄── reactivation ──┐
│ open │ │
└──────┬──────┘ │
│ assessment │
┌──────────────┼──────────────┐ │
▼ ▼ ▼ │
┌──────────┐ ┌────────────┐ ┌──────────────┐ │
│ verified │─►│ suspended │ │ not_accepted │ │
└──────────┘ └─────┬──────┘ └──────────────┘ │
│ │
└───────────────────────────┘
Every company you onboard through the API enters at created and moves to open once the merchant completes the form. From verified, a company can be suspended after a periodic review. A suspended company can be reactivated on your request, which puts it back into open for re-assessment (it does not jump straight back to verified). not_accepted is terminal.
Next action
next_action tells you what has to happen for the company to move forward. Its type is a stable enum, and when the action is "the merchant must complete onboarding", it carries the link.
next_action.type | When it appears |
|---|---|
provide_information | The merchant must open the onboarding link and submit information (initial onboarding, or supplementary documents after review). Carries onboarding_url. |
await_assessment | Information has been submitted and Rootline is assessing. Nothing for you or the merchant to do. |
review_information | A verified company needs a review action (e.g. annual KYC refresh, event-driven review). |
When more context is useful, next_action.comment carries a human-friendly free-text message from Rootline with details about what is expected, for example which specific document needs to be re-uploaded. You can surface it directly to the merchant or use it internally.
When no action is required (terminal states, or while suspended), next_action is absent.
Integration steps
Step 1. Create the company
POST /v1/companies
x-api-key: <your-api-key>
rootline-version: 2024-04-23
Content-Type: application/json
{
"legal_name": "Coffee Corner B.V.",
"trade_name": "Coffee Corner",
"description": "Specialty coffee bar in Amsterdam",
"address": {
"city": "Amsterdam",
"country": "NL"
},
"reference": "partner-internal-id-42"
}
The namespace is derived from your API key, so you cannot pass an arbitrary namespace.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
legal_name | string | Yes | The legal name of the company. |
trade_name | string | No | The public-facing name, or "doing business as" (DBA) name. Provide if it differs from the legal name. |
description | string | No | A description of the company. |
address | object | No | Merchant address. Fields: street_address, street_address2, postal_code, city, state, country (ISO 3166-1 alpha-2). |
reference | string | No | Your own reference to identify the company (e.g. your internal ID). |
legal_name is the only required field.
Step 2. Read the response
A successful create returns 200 with the full company object. The company starts in created, and next_action carries the company-specific onboarding link.
{
"id": "co_8f3a2b1c",
"object": "company",
"created_at": "2026-06-24T10:30:00Z",
"legal_name": "Coffee Corner B.V.",
"trade_name": "Coffee Corner",
"description": "Specialty coffee bar in Amsterdam",
"address": {
"city": "Amsterdam",
"country": "NL"
},
"reference": "partner-internal-id-42",
"verification_status": "created",
"next_action": {
"type": "provide_information",
"onboarding_url": "https://onboarding.rootline.com/roasters.com/companies/co_8f3a2b1c"
}
}
Store the id against your merchant record. The onboarding_url is unique to this company and is the link you redirect the merchant to.
Step 3. Redirect the merchant to the onboarding URL
Redirect the merchant to next_action.onboarding_url. They complete the onboarding form and accept Terms of Service.
To help the merchant prepare, share the Merchant Onboarding Requirements checklist ahead of time. It lists the information and documents they need to have ready before opening the form.
Step 4. Merchant completes onboarding
On submission, the same company transitions:
verification_status:createdtoopennext_action.type:provide_informationtoawait_assessment
No new company is created. The existing co_8f3a2b1c is updated in place, so the submission is pre-associated to the company you already hold.
Step 5. Track progress
You can follow a company's progress in three ways:
-
Subscribe to webhooks for push notifications on every status or next-action change.
-
Retrieve the company at any time to read its current
verification_statusandnext_action:GET /v1/companies/co_8f3a2b1c
x-api-key: <your-api-key>
rootline-version: 2024-04-23 -
Inspect all companies and their statuses in the Rootline Dashboard: dashboard.rootline.com/companies (use dashboard.staging.rootline.com/companies for staging).
Verification resolves to verified, not_accepted, or suspended, and next_action may ask for supplementary information along the way (provide_information again, carrying a fresh link).
Updating company information
A verified company retains its onboarding_url. When the merchant opens that URL, the form confirms that all required information has been provided and offers an Update my information option. From there they can update fields such as VAT number, UBOs, or bank account details.
A single onboarding URL is sufficient for the lifetime of the company: you do not need to generate a new URL when the merchant wants to make changes after verification.
Scenario testing
On staging the onboarding flow runs end-to-end automatically: once the merchant submits the form, the company is verified and the account is created without any involvement from Rootline operations.
You can drive a specific scenario by appending scenario=<value> to the onboarding_url before redirecting the merchant to the form. For example:
https://onboarding.staging.rootline.com/roasters.com/companies/co_8f3a2b1c?scenario=provide_information
scenario | Outcome |
|---|---|
| (not provided) | Happy flow: the merchant submits the form and the company is verified. |
provide_information | After submission, Rootline requests additional information from the merchant. |
Test credentials
On staging, merchants can complete the form without real bank, VAT or identity details:
- Test IBAN: any IBAN whose check digits are
00(e.g.NL00RABO0000000000). Passes IBAN validation and the account-name check. - Test VAT: any VAT number whose national part is all zeros (e.g.
NL000000000000). Passes VAT verification without being checked against VIES. - Test identity document: upload any file that is not a real ID document (e.g. a random PDF or screenshot). The form fills in fictitious "John Doe" details and shows a notice that the values are for testing.
When is what created?
| Event | What happens | Resulting verification_status | next_action.type |
|---|---|---|---|
You call POST /v1/companies | Company created with the data you supplied | created | provide_information |
| Merchant submits the form and accepts ToS | Existing company updated in place | open | await_assessment |
| Post-assessment, more info needed | Company updated | open | provide_information |
| No response after the non-response window | Company updated | suspended | (none) |
| Duplicate or stale onboarding detected | Company updated | suspended | (none) |
| Verification approved | Company updated | verified | (none) |
| Verified, periodic review triggered | Company updated | verified | review_information |
| Verified, supplementary info needed | Company updated | verified | provide_information |
| Rejected | Company updated | not_accepted | (none) |
Every company you create through the API starts in created and moves to open only once the merchant submits the form and accepts Terms of Service.
Webhooks
Subscribe to webhook events to be notified about company lifecycle changes without polling. Each event is delivered to your configured webhook endpoint and carries the company object as it stood at event_time. Event types follow the resource.action pattern (e.g. company.created).
The three events to subscribe to for onboarding are:
| Event type | When it fires |
|---|---|
company.created | A company is created, either by your POST /v1/companies call or by a merchant submitting the global onboarding link. |
company.verification_status.updated | The company's verification_status changed (e.g. created → open, open → verified). |
company.next_action.updated | The company's next_action changed, typically a request for supplementary information, or the action being cleared. |
livemode distinguishes test from production traffic, and api_version records the API version the payload is serialized against. Webhook endpoints are configured per account, not per request.
company.created
Fires once per company, when the company first appears in Rootline. For your API-driven flow that is the moment your POST /v1/companies returns; the company is in verification_status: created and the merchant has not yet submitted anything. Use this event to confirm the company landed and to record its id against your merchant record.
{
"object": "event",
"webhook_endpoint_id": "webh_4WxqjT0YfsxXDeKPbrwRie",
"event_type": "company.created",
"event_time": "2026-06-24T14:18:11.435566Z",
"livemode": false,
"api_version": "2024-04-23",
"company": {
"id": "co_5IGIrh15JJZ5oKSYubFpEr",
"object": "company",
"legal_name": "Trader Joe's",
"trade_name": "TraderJoes",
"created_at": "2026-06-24T14:18:11.422Z",
"reference": "myRefForUser1"
}
}
company.verification_status.updated
Fires whenever the company's verification_status changes. The transitions you can expect are created → open (merchant submitted the form), open → verified (assessment passed), open → not_accepted (rejected), and verified ↔ suspended (e.g. after a periodic review). The payload carries the new status, so a single handler can drive your internal merchant state from this event alone.
{
"object": "event",
"webhook_endpoint_id": "webh_4WxqjT0YfsxXDeKPbrwRie",
"event_type": "company.verification_status.updated",
"event_time": "2026-06-24T14:18:11.435566Z",
"livemode": false,
"api_version": "2024-04-23",
"company": {
"id": "co_5IGIrh15JJZ5oKSYubFpEr",
"object": "company",
"legal_name": "Trader Joe's",
"trade_name": "TraderJoes",
"created_at": "2026-06-24T14:18:11.422Z",
"reference": "myRefForUser1",
"verification_status": "verified"
}
}
company.next_action.updated
Fires whenever the company's next_action changes. Most commonly when Rootline needs more information from the merchant (type: provide_information, with the onboarding_url to send them to), when a submission moves the company back into review (await_assessment), or when a verified company is due for a review (review_information). When the action is provide_information, forward the onboarding_url to the merchant; the same URL is reused for the lifetime of the company.
{
"object": "event",
"webhook_endpoint_id": "webh_4WxqjT0YfsxXDeKPbrwRie",
"event_type": "company.next_action.updated",
"event_time": "2026-06-24T14:18:11.435566Z",
"livemode": false,
"api_version": "2024-04-23",
"company": {
"id": "co_5IGIrh15JJZ5oKSYubFpEr",
"object": "company",
"legal_name": "Trader Joe's",
"trade_name": "TraderJoes",
"created_at": "2026-06-24T14:18:11.422Z",
"reference": "myRefForUser1",
"verification_status": "open",
"next_action": {
"type": "provide_information",
"onboarding_url": "https://onboarding.rootline.com/roasters.com/companies/co_5IGIrh15JJZ5oKSYubFpEr"
}
}
}