Skip to content

Platform — Clients and projects

A platform team that opens projects on behalf of its clients uses this API to register a client, show the client’s verification link in its own onboarding, open projects, take them live and set their payout account. Everything the Clients menu of the dashboard does is available here.

These endpoints take a team token, not a project token: create one under the account-level API tokens menu (visible to the team owner). A team token is also valid on the project endpoints of every project of the team, yours and your clients’, so one token is enough to create checkouts and invoices in a client’s project. See API token.

Authorization: Bearer <team token>

A project token or a legacy token returns 403.

Field Type Description
id Number The client’s (business) ID. The business_id of webhook payloads.
client_reference_id String Your own ID for the client.
name String Business name, copied from TrustAPI once verified; null before.
type String Business type (person, company …), once verified.
contact_email String Where the verification link is sent.
phone String Phone, once verified.
status String Onboarding status, see below.
is_verified Boolean Every step done: the client’s projects can go live.
verified_at Date When that happened.
verification_status String Status of the current TrustAPI attempt (pending, submitted, under_review, verified, rejected, expired).
steps Array trustapi, qpay, bank, each with status (pending, in_progress, done, error) and error.
qpay_merchant_id String The QPay merchant created for the client.
bank_accounts Array Active bank accounts (id, bank_code, bank_name, account_number, account_name).
projects Array Projects opened for the client (id, name, mode). Retrieve only.
verification Object url, expires_at and emailed of the attempt just started. Only in the create and verification-link responses.
created_at Date When the client was registered.
status Meaning
not_started The client has not opened its link and submitted anything.
in_review Filling in or submitted, awaiting a decision.
incomplete Verified by TrustAPI; the QPay merchant and bank account are being set up.
verified Every step done.
rejected Rejected. Sending the link again starts a new attempt.
expired The link expired. Send it again.
POST /v1/clients
Parameter Type Required Description
email String true The client’s email. The verification link goes there.
client_reference_id String false Your own ID for the client. Up to 48 characters, unique per team.

The client is created, its verification starts on TrustAPI and the link is emailed. verification.url in the response is that link: show it in your own onboarding page. A second client with the same email or client_reference_id is refused (422).

Example request

Терминал
BYL_TEAM_TOKEN="your team token"
curl -X POST https://byl.mn/api/v1/clients \
-H "Authorization: Bearer $BYL_TEAM_TOKEN" \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"client_reference_id": "shop_42"
}'

Example response

{
"data": {
"id": 118,
"client_reference_id": "shop_42",
"name": null,
"type": null,
"contact_email": "[email protected]",
"phone": null,
"status": "in_review",
"is_verified": false,
"verified_at": null,
"verification_status": "pending",
"steps": [
{ "key": "trustapi", "status": "in_progress", "error": null },
{ "key": "qpay", "status": "pending", "error": null },
{ "key": "bank", "status": "pending", "error": null }
],
"qpay_merchant_id": null,
"bank_accounts": [],
"verification": {
"url": "https://trustapi.dotly.mn/verify/tok_8f2a…",
"expires_at": "2026-11-04T09:00:00+08:00",
"emailed": true
},
"created_at": "2026-10-28T09:00:00.000000Z",
"updated_at": "2026-10-28T09:00:00.000000Z"
}
}
GET /v1/clients/:client_id
GET /v1/clients/by-client-reference-id/:client_reference_id

The response includes the client’s projects. Each retrieve re-checks the status with TrustAPI, so it is right even when a webhook was missed. Another team’s client returns 404.

Терминал
curl https://byl.mn/api/v1/clients/by-client-reference-id/shop_42 \
-H "Authorization: Bearer $BYL_TEAM_TOKEN" \
-H 'Accept: application/json'
GET /v1/clients
Parameter Type Description
status String Filter by onboarding status.
per_page Number Page size (default 25, at most 100).

Newest first, paginated (meta.total, links.next).

POST /v1/clients/:client_id/verification-link

When the client lost its link, the link expired or the attempt was rejected, this creates a (new) link and emails it; the response carries verification.url. It is refused with 409 when:

error Meaning
already_verified The client is already verified.
in_review Submitted and awaiting a decision: nothing is left to fill in.
onboarding_in_progress Verified by TrustAPI; the remaining steps are completing automatically.

When the verification service does not answer: 503 verification_unavailable.

Field Type Description
id Number Project ID, used on the project endpoints.
name String Name.
mode String Test or Live.
business_id Number The client the project runs under. null for the team’s own projects.
email String Where the merchant gets notices (bank transfer notices).
support_email String The email customers see, or null (customers then see email).
support_phone String The phone number customers see, or null.
qpay_merchant_id String The QPay merchant linked to the project; linked automatically once the client is verified.
payout_bank_account Object The account the project pays out to (id, bank_code, bank_name, account_number, account_name, is_active), or null.
created_at Date Created at.
POST /v1/projects
Parameter Type Required Description
name String true Project name. Up to 255 characters.
business_id Number false The client’s id. Omit for a project under your own business.

A verified client’s QPay merchant is linked to the new project right away; otherwise it is linked once the client is verified. A team without a plan can have one project (422 subscription_required); at the plan’s limit, 422 project_limit_reached.

Терминал
curl -X POST https://byl.mn/api/v1/projects \
-H "Authorization: Bearer $BYL_TEAM_TOKEN" \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{ "name": "Shop 42", "business_id": 118 }'
{
"data": {
"id": 57,
"name": "Shop 42",
"mode": "Test",
"business_id": 118,
"email": "[email protected]",
"support_email": null,
"support_phone": null,
"qpay_merchant_id": null,
"payout_bank_account": null,
"created_at": "2026-10-28T09:05:00.000000Z",
"updated_at": "2026-10-28T09:05:00.000000Z"
}
}
GET /v1/projects/:project_id
GET /v1/projects

The list returns every project of the team (yours and your clients’), newest first; business_id narrows it to one client. per_page as above.

GET /v1/projects/:project_id/bank-accounts
PUT /v1/projects/:project_id/bank-account

GET lists the active accounts of the business the project runs under (the client’s); the account the client gave TrustAPI is added automatically when it is verified. PUT with bank_account_id makes one of them the project’s payout account; another business’s account is refused with 422. A payout account is required before going live.

PUT /v1/projects/:project_id/mode
Parameter Type Required Description
mode String true Test or Live.

Going live needs a verified business, an active plan on the team and a payout account on the project; the error of the 422 names what is missing: business_not_verified, subscription_required, payout_account_required. The current mode is accepted as a no-op 200.

Once a project is open, call its checkout, invoice and customer endpoints with the same team token, with the returned id as :project_id. To receive the events of every project in one place, register a team webhook endpoint: the business_id of each payload tells which client it belongs to.

In a client’s project a bank transfer lands in the client’s account, so only the client can see the statement. As soon as the customer clicks “I’ve transferred”, Byl emails the client’s contact address a time-limited link that needs no login, where the client answers “Received” / “Not received”. The team owner gets a copy for the record (or, when the project has a Telegram/Discord channel, the channel does instead).

To do this in your own UI, show the team webhook’s payment.awaiting_verification event to your client and send their answer back through the Bank transfers API. Whichever path decides first wins.

  • API token — creating a team token
  • Webhook — team endpoints and business_id
  • Checkout — taking payments in a client’s project
  • Bank transfers — confirming bank transfers over the API