Skip to Content
APIAPI calls & examples

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}
SegmentDescriptionExample
{scopeId}Organization UUID or branch UUID, depending on the resource123e4567-e89b-12d3-a456-426614174000
{resource}Resource nameaccounts

Full example:

GET https://api.routix.com/v1/550e8400-e29b-41d4-a716-446655440000/accounts

Authentication

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:

  • branches
  • organizations
  • users
  • master_data

Branch-scoped resources use the branch UUID in the path, for example:

  • accounts
  • projects
  • shipments
  • trips
  • items
  • tariffs
  • zones
  • quotations

Supported query parameters

ParameterTypeDefaultDescription
limitinteger50Number of records per page
offsetinteger0Pagination offset
sortstring-Sort expression in the format field:asc or field:desc
filterstring-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:value

You 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,carrier

Supported operators

OperatorMeaning
eqExact match
neNot equal
inValue is part of a list
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
likeCase-sensitive text match
ilikeCase-insensitive text match
isnullNull check

Important rules

  • Filtering and sorting are whitelisted per resource.
  • organization_id and branch_id are 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:desc

Full example call

GET /v1/{scopeId}/accounts?limit=25&offset=0&sort=company_name:asc&filter=status:eq:active&filter=account_type:in:customer,carrier

Use 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

CodeMeaning
200Success
400Bad request, invalid parameters
401Unauthorized, missing or expired token
403Forbidden, insufficient scope or scope access
404Not found, invalid organization UUID, branch UUID, or resource
405Method not allowed
429Rate limited
500Internal 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

ResourceRequired scopeScope type
accountsroutix:accounts:writeBranch UUID
ordersroutix:orders:writeBranch UUID
projectsroutix:projects:writeBranch UUID
quotationsroutix:quotations:writeBranch UUID
shipmentsroutix:shipments:writeBranch UUID
tripsroutix:trips:writeBranch UUID
vehiclesroutix:vehicles:writeOrganization UUID
invoicesroutix:invoices:writeBranch UUID
itemsroutix:items:writeBranch UUID, branch-or-null resource
tariffsroutix:tariffs:writeBranch UUID, branch-or-null resource
zonesroutix:zones:writeBranch UUID, branch-or-null resource

PATCH example

PATCH /v1/{scopeId}/accounts/{id}
{ "status": "active", "company_name": "Acme Transport B.V." }

PATCH error codes

CodeError
400invalid_request
400invalid_update
401unauthorized
401invalid_token
403invalid_token_type
403insufficient_scope
404not_found
405method_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_id and branch_id are set server-side and cannot be controlled by the client.

Supported POST resources and scopes

ResourceRequired scopeScope type
accountsroutix:accounts:writeBranch UUID
ordersroutix:orders:writeBranch UUID
projectsroutix:projects:writeBranch UUID
quotationsroutix:quotations:writeBranch UUID
shipmentsroutix:shipments:writeBranch UUID
tripsroutix:trips:writeBranch UUID
vehiclesroutix:vehicles:writeOrganization UUID
invoicesroutix:invoices:writeBranch UUID
itemsroutix:items:writeBranch UUID, branch-or-null resource
tariffsroutix:tariffs:writeBranch UUID, branch-or-null resource
zonesroutix:zones:writeBranch 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

CodeError
400invalid_request
400invalid_create
400create_failed
401unauthorized
401invalid_token
403invalid_token_type
403insufficient_scope
404not_found
405method_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.
  • DELETE uses the same write scope as POST and PATCH.
  • A resource ID in the URL is required.
  • No request body is needed.

Supported DELETE resources and scopes

ResourceRequired scopeScope type
accountsroutix:accounts:writeBranch UUID
ordersroutix:orders:writeBranch UUID
projectsroutix:projects:writeBranch UUID
quotationsroutix:quotations:writeBranch UUID
shipmentsroutix:shipments:writeBranch UUID
tripsroutix:trips:writeBranch UUID
vehiclesroutix:vehicles:writeOrganization UUID
invoicesroutix:invoices:writeBranch UUID
itemsroutix:items:writeBranch UUID, branch-or-null resource
tariffsroutix:tariffs:writeBranch UUID, branch-or-null resource
zonesroutix:zones:writeBranch UUID, branch-or-null resource

DELETE example

DELETE /v1/{scopeId}/accounts/{id}

DELETE example for quotations

DELETE /v1/{scopeId}/quotations/{id}

DELETE error codes

CodeError
400invalid_request
401unauthorized
401invalid_token
403invalid_token_type
403insufficient_scope
404not_found
405method_not_allowed

Rate limits

EndpointLimit
REST API1000 requests per minute per organization
Edge Functions100 requests per minute per user
Token endpoint30 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");
  • API integration
  • Accounts
  • Setup guide
Last updated on