API calls & examples
The Routix API is a versioned REST API accessible through the API proxy. All requests require a valid OAuth token.
User level: Advanced
Base URL
https://api.routix.com/v1/{scopeId}/{resource}| Segment | Description | Example |
|---|---|---|
{scopeId} | Organization UUID or branch UUID, depending on the resource | 123e4567-e89b-12d3-a456-426614174000 |
{resource} | Resource name | accounts |
Full example:
GET https://api.routix.com/v1/550e8400-e29b-41d4-a716-446655440000/accountsAuthentication
Include the OAuth access token in every request:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Only OAuth tokens are accepted. Regular Routix user tokens are rejected by the API proxy.
Route patterns
Resource calls follow this pattern:
/v1/{scopeId}/{resource}Update calls follow this pattern:
/v1/{scopeId}/{resource}/{id}Organization-scoped resources use the organization UUID in the path:
branchesorganizationsusersmaster_data
Branch-scoped resources use the branch UUID in the path, for example:
accountsprojectsshipmentstripsitemstariffszonesquotations
Supported query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Number of records per page |
offset | integer | 0 | Pagination offset |
sort | string | - | Sort expression in the format field:asc or field:desc |
filter | string | - | Filter expression in the format field:operator:value |
Filtering and sorting
The API supports a generic query syntax for list calls.
Syntax
sort=field:asc
sort=field:desc
filter=field:operator:valueYou can repeat filter to send multiple filters in the same request.
Example:
?limit=25&offset=0&sort=company_name:asc&filter=status:eq:active&filter=account_type:in:customer,carrierSupported operators
| Operator | Meaning |
|---|---|
eq | Exact match |
ne | Not equal |
in | Value is part of a list |
gt | Greater than |
gte | Greater than or equal |
lt | Less than |
lte | Less than or equal |
like | Case-sensitive text match |
ilike | Case-insensitive text match |
isnull | Null check |
Important rules
- Filtering and sorting are whitelisted per resource.
organization_idandbranch_idare reserved for server-side scoping and cannot be filtered by clients.- Tenant scope always remains server-controlled.
- Not every field is filterable or sortable for every resource.
Filter examples
?filter=status:eq:active
?filter=account_type:in:customer,carrier
?filter=created_at:gte:2026-01-01
?filter=company_name:ilike:%transport%
?filter=valid_until:lt:2026-12-31
?filter=comment:isnull:true
?sort=company_name:asc
?sort=created_at:descFull example call
GET /v1/{scopeId}/accounts?limit=25&offset=0&sort=company_name:asc&filter=status:eq:active&filter=account_type:in:customer,carrierUse a branch UUID for branch-scoped resources such as accounts, orders, quotations, shipments, trips, items, tariffs, and zones.
Use an organization UUID for organization-scoped resources such as branches, organizations, users, and master_data.
Shared response shape
All list calls use the same base structure:
{
"data": [],
"pagination": {
"limit": 50,
"offset": 0,
"total": 123
},
"version": "v1"
}HTTP status codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request, invalid parameters |
| 401 | Unauthorized, missing or expired token |
| 403 | Forbidden, insufficient scope or scope access |
| 404 | Not found, invalid organization UUID, branch UUID, or resource |
| 405 | Method not allowed |
| 429 | Rate limited |
| 500 | Internal server error |
PATCH updates
The API supports updates through PATCH for a limited set of resources.
Endpoint pattern
PATCH /v1/{scopeId}/{resource}/{id}Update rules
- Use a branch UUID as
{scopeId}for branch-scoped resources. - Use an organization UUID as
{scopeId}for organization-scoped resources. - The API always validates server-side whether the resource belongs to the allowed organization and branch.
- Only explicitly allowed fields per resource can be updated.
- Unknown or disallowed fields return
400 invalid_update. - The request body must be a JSON object.
Supported PATCH resources and scopes
| Resource | Required scope | Scope type |
|---|---|---|
accounts | routix:accounts:write | Branch UUID |
orders | routix:orders:write | Branch UUID |
projects | routix:projects:write | Branch UUID |
quotations | routix:quotations:write | Branch UUID |
shipments | routix:shipments:write | Branch UUID |
trips | routix:trips:write | Branch UUID |
vehicles | routix:vehicles:write | Organization UUID |
invoices | routix:invoices:write | Branch UUID |
items | routix:items:write | Branch UUID, branch-or-null resource |
tariffs | routix:tariffs:write | Branch UUID, branch-or-null resource |
zones | routix:zones:write | Branch UUID, branch-or-null resource |
PATCH example
PATCH /v1/{scopeId}/accounts/{id}{
"status": "active",
"company_name": "Acme Transport B.V."
}PATCH error codes
| Code | Error |
|---|---|
| 400 | invalid_request |
| 400 | invalid_update |
| 401 | unauthorized |
| 401 | invalid_token |
| 403 | invalid_token_type |
| 403 | insufficient_scope |
| 404 | not_found |
| 405 | method_not_allowed |
POST creates
The API supports create actions through POST for a limited set of resources.
Endpoint pattern
POST /v1/{scopeId}/{resource}Create rules
- Use a branch UUID as
{scopeId}for branch-scoped resources. - Use an organization UUID as
{scopeId}for organization-scoped resources. - The API always validates server-side whether the resource belongs to the allowed organization and branch.
- Only explicitly allowed fields per resource can be sent.
- Unknown or disallowed fields return
400 invalid_create. - The request body must be a JSON object.
organization_idandbranch_idare set server-side and cannot be controlled by the client.
Supported POST resources and scopes
| Resource | Required scope | Scope type |
|---|---|---|
accounts | routix:accounts:write | Branch UUID |
orders | routix:orders:write | Branch UUID |
projects | routix:projects:write | Branch UUID |
quotations | routix:quotations:write | Branch UUID |
shipments | routix:shipments:write | Branch UUID |
trips | routix:trips:write | Branch UUID |
vehicles | routix:vehicles:write | Organization UUID |
invoices | routix:invoices:write | Branch UUID |
items | routix:items:write | Branch UUID, branch-or-null resource |
tariffs | routix:tariffs:write | Branch UUID, branch-or-null resource |
zones | routix:zones:write | Branch UUID, branch-or-null resource |
POST example
POST /v1/{scopeId}/accounts{
"company_name": "Acme Transport B.V.",
"email": "[email protected]",
"phone": "+31 20 123 4567",
"account_type": "customer",
"status": "active"
}POST error codes
| Code | Error |
|---|---|
| 400 | invalid_request |
| 400 | invalid_create |
| 400 | create_failed |
| 401 | unauthorized |
| 401 | invalid_token |
| 403 | invalid_token_type |
| 403 | insufficient_scope |
| 404 | not_found |
| 405 | method_not_allowed |
DELETE deletes
The API supports delete actions through DELETE for a limited set of resources.
Endpoint pattern
DELETE /v1/{scopeId}/{resource}/{id}Delete rules
- Use a branch UUID as
{scopeId}for branch-scoped resources. - Use an organization UUID as
{scopeId}for organization-scoped resources. - The API always validates server-side whether the resource belongs to the allowed organization and branch.
DELETEuses the same write scope asPOSTandPATCH.- A resource ID in the URL is required.
- No request body is needed.
Supported DELETE resources and scopes
| Resource | Required scope | Scope type |
|---|---|---|
accounts | routix:accounts:write | Branch UUID |
orders | routix:orders:write | Branch UUID |
projects | routix:projects:write | Branch UUID |
quotations | routix:quotations:write | Branch UUID |
shipments | routix:shipments:write | Branch UUID |
trips | routix:trips:write | Branch UUID |
vehicles | routix:vehicles:write | Organization UUID |
invoices | routix:invoices:write | Branch UUID |
items | routix:items:write | Branch UUID, branch-or-null resource |
tariffs | routix:tariffs:write | Branch UUID, branch-or-null resource |
zones | routix:zones:write | Branch UUID, branch-or-null resource |
DELETE example
DELETE /v1/{scopeId}/accounts/{id}DELETE example for quotations
DELETE /v1/{scopeId}/quotations/{id}DELETE error codes
| Code | Error |
|---|---|
| 400 | invalid_request |
| 401 | unauthorized |
| 401 | invalid_token |
| 403 | invalid_token_type |
| 403 | insufficient_scope |
| 404 | not_found |
| 405 | method_not_allowed |
Rate limits
| Endpoint | Limit |
|---|---|
| REST API | 1000 requests per minute per organization |
| Edge Functions | 100 requests per minute per user |
| Token endpoint | 30 requests per minute per client |
When you receive a 429, implement exponential backoff with jitter.
Code examples
These examples are intentionally generic: first request a token, then call any resource path within the same organization or branch scope.
JavaScript / Node.js
const ROUTIX_URL = 'https://api.routix.com';
async function getToken(clientId, clientSecret) {
const res = await fetch(`${ROUTIX_URL}/v1/oauth/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
}),
});
if (!res.ok) {
const err = await res.json();
throw new Error(`Auth failed: ${err.error_description}`);
}
const data = await res.json();
return data.access_token;
}
async function callApi(token, scopeId, resourcePath) {
const url = `${ROUTIX_URL}/v1/${scopeId}/${resourcePath}`;
const res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) {
const err = await res.json();
throw new Error(`API error: ${err.error_description}`);
}
return res.json();
}Python
import requests
ROUTIX_URL = "https://api.routix.com"
def get_token(client_id: str, client_secret: str) -> str:
response = requests.post(
f"{ROUTIX_URL}/v1/oauth/token",
json={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
},
)
response.raise_for_status()
return response.json()["access_token"]
def call_api(token: str, scope_id: str, resource_path: str) -> dict:
response = requests.get(
f"{ROUTIX_URL}/v1/{scope_id}/{resource_path}",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status()
return response.json()PHP
<?php
$routixUrl = 'https://api.routix.com';
function getToken(string $clientId, string $clientSecret): string {
global $routixUrl;
$ch = curl_init("$routixUrl/v1/oauth/token");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'grant_type' => 'client_credentials',
'client_id' => $clientId,
'client_secret' => $clientSecret,
]),
]);
$response = json_decode(curl_exec($ch), true);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('Auth failed: ' . ($response['error_description'] ?? 'Unknown error'));
}
return $response['access_token'];
}
function callApi(string $token, string $scopeId, string $resourcePath): array {
global $routixUrl;
$ch = curl_init("$routixUrl/v1/$scopeId/$resourcePath");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
]);
$response = json_decode(curl_exec($ch), true);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('API error: ' . ($response['error_description'] ?? 'Unknown error'));
}
return $response;
}C# / .NET
using System.Net.Http.Headers;
using System.Net.Http.Json;
var routixUrl = "https://api.routix.com";
var httpClient = new HttpClient();
var tokenResponse = await httpClient.PostAsJsonAsync(
$"{routixUrl}/v1/oauth/token",
new {
grant_type = "client_credentials",
client_id = "your-client-id",
client_secret = "routix_a1b2c3d4..."
});
var tokenData = await tokenResponse.Content.ReadFromJsonAsync<Dictionary<string, object>>();
var token = tokenData!["access_token"].ToString();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var response = await httpClient.GetFromJsonAsync<object>(
$"{routixUrl}/v1/550e8400-e29b-41d4-a716-446655440000/accounts?limit=25&offset=0&sort=company_name:asc&filter=status:eq:active");Related pages
- API integration
- Accounts
- Setup guide

