#Client accounts
For agencies running one Ready account per customer. Each client account has its own numbers, 10DLC registration, card and balance, and pays for its own texts.
Details
Call these with an rsms_ key from your own account.
Two kinds of sub-account. An independent sub-account (account_kind: "client") pays from its own card and balance. A Workspace in the guides is different: your main account's balance pays for it.
Markup and how you're paid
Markup can't be set anymore: any markup above 0 is refused with 400. Set your clients' prices with partner fees on the Partner page. It's in the Agency view: click your business name in the top bar, then Agency view. A client that already pays a markup keeps paying it, as described below.
Details
- Price: a client pays your base rate plus your markup per segment (Set a client's markup).
- Payout: markup goes to your reseller balance, only for texts a client sends after it submits its 10DLC registration. Earlier texts aren't credited later. You earn no affiliate commission on your own clients.
Acting as a client
Add X-Sub-Account-Id: <client id> to any /v1 API-key request to run it as that client: what you create is the client's, and its card and balance pay.
Details
The key can be sent as X-API-Key or Authorization: Bearer. Your own numbers aren't visible while you act as a client. Buy with POST /v1/numbers/checkout, not /phone-numbers/checkout.
Buy a number for a client: POST /v1/numbers/checkout then POST /v1/numbers, both with the header (a payment your own account made also works for the second call). Then poll GET /v1/numbers/:id, with the header, until it's active.
Refusals (nothing runs):
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_sub_account_id | Not a numeric id (also 0 or empty). |
| 400 | sub_account_header_not_supported | Path outside /v1. |
| 400 | sub_account_header_needs_api_key | No rsms_ API key. |
| 403 | sub_account_forbidden | Not a client you manage (including your own id). |
| 403 | sub_account_suspended | Client suspended. |
| 404 | sub_account_not_found | No account has that id. |
| 503 | AUTH_CHECK_UNAVAILABLE | Couldn't check. Nothing ran; retry. |
curl "https://api.tryready.com/v1/numbers" \
-H "X-API-Key: $READY_API_KEY" \
-H "X-Sub-Account-Id: 4812"
const res = await fetch('https://api.tryready.com/v1/numbers', {
headers: {
'X-API-Key': process.env.READY_API_KEY,
'X-Sub-Account-Id': '4812',
},
});
const json = await res.json();
if (!res.ok || json.success === false) {
throw new Error(`${res.status} ${json.error_code || json.code}: ${json.error}`);
}
import os, requests
r = requests.get(
"https://api.tryready.com/v1/numbers",
headers={"X-API-Key": os.environ["READY_API_KEY"], "X-Sub-Account-Id": "4812"},
timeout=30,
)
data = r.json()
if not r.ok or data.get("success") is False:
raise RuntimeError(f'{r.status_code} {data.get("error_code") or data.get("code")}: {data.get("error")}')
#Create a client account
/v1/sub-accountsCreates a client account with its own login, card, numbers and registration.
Body parameters
emailstringRequired- The client owner's email.
first_name, last_namestringOptionalcompany_namestringOptionalsend_invitebooleanOptionalDefaulttrue- Emails the client an invite to set up their login and card.
Details
Sendfalseto skip the email and send theminvite_linkyourself. billingstringOptionalDefaultclientclient: the client adds their own card and pays their own bill.agency: your card pays for the client’s registration, numbers and messages, at your prices.
Returns
dataobjectid(use it asX-Sub-Account-Id),email,company_name,account_kind: "client",client_rate,invite_link.Details
client_rateis what the client pays per segment (your base rate plus your default markup). It'snullunless your markup is on and your default markup is above 0.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_request | Missing email. |
| 400 | unknown_field | A field it doesn't accept. |
| 403 | agency_only | Your account is another agency's client or workspace. |
| 409 | client_already_yours | Already your client. |
| 409 | email_reserved | Email can't be used (403 for a staff address). |
#List client accounts
/v1/sub-accountsThe client accounts you manage, newest first. Pages with a cursor.
Query parameters
limitintegerOptionalDefault50Max200- Page size.
before_idintegerOptional- The
next_before_idfrom the previous page.
Returns
data[]object[]id,email,first_name,last_name,company_name,status,markup_usd_per_segment,created_at.has_moreboolean- Today it's
trueon any full page, even if nothing follows. Page untildatais empty. next_before_idinteger | null- Pass as
before_id.
Errors
| HTTP | Code | When |
|---|---|---|
| 403 | permission_denied | The key lacks team management (all four endpoints). |
#Get a client account
/v1/sub-accounts/:idOne client account.
Path parameters
idintegerRequired- The client account id.
Errors
| HTTP | Code | When |
|---|---|---|
| 404 | sub_account_not_found | Not a client you manage. |
#Set a client's markup
/v1/sub-accounts/:id/rateWhat the client pays you per segment on top of your own rate. Any markup above 0 is refused now; set prices with partner fees on the Partner page, in the Agency view.
Path parameters
idintegerRequired- The client account id.
Body parameters
markupnumberOptional- Dollars per segment, from 0 to 0.06.
use_defaultbooleanOptionaltrueto use your default markup instead.dialer_markup, use_default_dialernumber, booleanOptional- The same, for calls.
Returns
dataobjectmarkup,is_custom,base_rate(your rate),client_rate(the client's per-segment price).
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_request | Negative markup, or nothing to change. |
| 400 | unknown_field | A field it doesn't accept. |
| 400 | terms_required | Reseller terms not accepted. |
| 400 | invalid_markup | Above $0.06 a segment. |
| 403 | reseller_not_approved | Markup above 0, setup under review. |
| 403 | forbidden | Markup above 0 while markup is off, or not your main account. |
| 404 | sub_account_not_found | Not a client you manage. |
| 409 | rate_locked | Rate locked; contact support. |