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.
Team token
Section titled “Team token”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.
The Client object
Section titled “The Client object”| 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. |
Onboarding status
Section titled “Onboarding status”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. |
Create a client
Section titled “Create a client”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, "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" }}Retrieve a client
Section titled “Retrieve a client”GET /v1/clients/:client_idGET /v1/clients/by-client-reference-id/:client_reference_idThe 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'List clients
Section titled “List clients”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).
Send the verification link
Section titled “Send the verification link”POST /v1/clients/:client_id/verification-linkWhen 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.
The Project object
Section titled “The Project object”| 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. |
Create a project
Section titled “Create a project”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, "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" }}Retrieve and list projects
Section titled “Retrieve and list projects”GET /v1/projects/:project_idGET /v1/projectsThe list returns every project of the team (yours and your clients’), newest first; business_id narrows it to one client. per_page as above.
Payout account
Section titled “Payout account”GET /v1/projects/:project_id/bank-accountsPUT /v1/projects/:project_id/bank-accountGET 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.
Switch the mode
Section titled “Switch the mode”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.
Working in a client’s project
Section titled “Working in a client’s project”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.
Confirming bank transfers
Section titled “Confirming bank transfers”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.
Next steps
Section titled “Next steps”- 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