OAuth reference
Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /auth/oauth/auth | None | Client credentials grant |
POST | /auth/oauth/token | None | Exchange a code or refresh |
GET | /auth/oauth/client | Bearer (login session) | Client details for the consent screen |
POST | /auth/get-one-time-token | Bearer (user session) | Mint a one-time token |
Hosts:
| Environment | Host |
|---|---|
| Production | https://api.bito.uz |
| Dev | https://api.systematicdev.uz |
Rate limit on /auth/oauth/auth, /auth/oauth/token and /auth/oauth/client: 20 requests per minute per IP. /auth/get-one-time-token is not rate-limited.
On the Integration API, webhook/subscribe and webhook/unsubscribe accept 1 request per second.
What Bito sends you
| Event | Method | Sent to | Payload |
|---|---|---|---|
| Install | POST | your redirect_uri | { code, client_id, account_id } |
| Uninstall | POST | your revoke_access_hook_uri | { account_id } |
| Data change | POST | each webhook destination | { collection_name, action, id, organization_id } |
The first two are signed with your client_secret (see Install & uninstall hooks for the X-Bito-Signature verification); the third is covered in Data webhooks.
Response envelope
Every Bito response — success or failure — uses the same envelope.
Success
json
{
"code": 0,
"message": "Success",
"messages": { "uz": "...", "ru": "...", "en": "Success" },
"data": {},
"time": "2025-01-15T10:30:00.000Z"
}Error
json
{
"code": 401,
"message": "Unauthorized user",
"messages": { "uz": "...", "ru": "...", "en": "Unauthorized user" },
"time": "2025-01-15T10:30:00.000Z"
}code is 0 on success. On failure it carries the error code, and data is absent. Branch on code, never on the text of message, which is localized.
Common errors
| HTTP | Error | What it means | Fix |
|---|---|---|---|
| 401 | Unauthorized | Missing or malformed Authorization header | Send Bearer <access_token> |
| 401 | Token expired | The access token is past its 24 hours | Refresh |
| 401 | Unauthorized | The session behind the token was terminated | Re-authorize. A secret rotation does exactly this. |
| 400 | Invalid credentials | client_id and client_secret do not match, or the code was already used | Check the secret; request a fresh code |
| 400 | Client not found | No client with that client_id | Check the id you copied at creation |
| 400 | Auth code expired | More than 20 minutes passed | Restart the flow |
| 400 | Invalid scope | A requested scope is not a known scope value | Fix the scope value |
| 429 | Too many requests | More than 20 auth calls in a minute from one IP | Back off; refresh on expiry, not per request |