Generated from the OpenAPI 3.1 document /partner-api/v1/openapi.json (version 1.0.0). Import it into your API client or code generator. Paths below include their API prefix.
Account
GET /partner-api/v1/me
Your partner account
Entitlement (active, restricted …), capabilities, limits (credit limit, rate limits, page size), the plans with your current price (keys with rate_card.read; other keys get price null), and the key making the request. Answers while the account is restricted so your integration can explain refused charge-creating calls.
Key: management key
| Status | Body | Meaning |
|---|---|---|
200 | Partner | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Partner)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (ptn_…) | yes | |
livemode | boolean | yes | |
mode | string (live, test) | yes | |
name | string | yes | Trading name (or legal name). |
legal_name | string | ||
entitlement | object | yes | |
capabilities | object | yes | |
limits | object | yes | |
plans | array of object | yes | |
credential | object | null | The API key making the request. | |
request_id | string |
GET /partner-api/v1/openapi.json
This OpenAPI document
Public, no authentication.
Key: none (public)
| Status | Body | Meaning |
|---|---|---|
200 | object | The OpenAPI 3.1 document. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
GET /partner-api/v1/ping
Check a management key
Who am I: the partner, mode, scopes and fleet scope of the key. Works even when the account is not active.
Key: management key
| Status | Body | Meaning |
|---|---|---|
200 | Ping | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Ping)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
ok | boolean | yes | |
livemode | boolean | yes | |
partner | string (ptn_…) | yes | |
credential | string | null (key_…) | ||
credential_class | string (management, tracking) | ||
scopes | array of string | ||
fleet_scope | string (all, selected) | ||
time | string (date-time) | ||
request_id | string |
Customers
GET /partner-api/v1/customers
List customers
Newest first. A key limited to fleets sees a customer only when one of its fleets is in scope.
Key: management key · Scope: customers.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
external_reference | query | string | Exact match on your own reference (case-sensitive). | |
status | query | string (active, closed) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Customer)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | yes | Your own id for this customer, unique per partner and mode. |
contact | object | yes | |
notes | string | null | ||
is_self | boolean | yes | The "own fleet" customer of your organisation. |
status | string (active, closed) | yes | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
POST /partner-api/v1/customers
Create a customer
external_reference is unique per partner and mode (case-sensitive): a second customer with the same reference answers 409 CONFLICT with details.field = "external_reference", details.reason = "duplicate_external_reference" and, when your key can see it, details.customer (the existing cus_ id). Resolve existing customers with GET /customers?external_reference=… before creating.
Key: management key · Scope: customers.write · Idempotency-Key required
Request body CustomerCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Your customer's business name. |
external_reference | string | Your own customer id; use it to find the customer again after a retry. 1–128 printable characters, case-sensitive. | |
is_self | boolean | Create your organisation's own "own fleet" customer (one per mode). | |
contact_name | string | ||
contact_email | string (email) | ||
contact_phone | string | ||
notes | string | Internal notes for your team (never shown to the customer). |
{
"name": "Acme Deliveries Ltd",
"external_reference": "C1042",
"contact_name": "Sam Patel",
"contact_email": "[email protected]"
}| Status | Body | Meaning |
|---|---|---|
201 | Customer | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Customer)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | yes | Your own id for this customer, unique per partner and mode. |
contact | object | yes | |
notes | string | null | ||
is_self | boolean | yes | The "own fleet" customer of your organisation. |
status | string (active, closed) | yes | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
{
"object": "customer",
"id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"name": "Acme Deliveries Ltd",
"external_reference": "C1042",
"contact": {
"name": "Sam Patel",
"email": "[email protected]",
"phone": null
},
"notes": null,
"is_self": false,
"status": "active",
"livemode": true,
"created_at": "2026-10-01T09:00:00Z",
"updated_at": "2026-10-01T09:00:00Z",
"closed_at": null
}GET /partner-api/v1/customers/{id}
Retrieve a customer
Key: management key · Scope: customers.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (cus_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Customer | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Customer)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | yes | Your own id for this customer, unique per partner and mode. |
contact | object | yes | |
notes | string | null | ||
is_self | boolean | yes | The "own fleet" customer of your organisation. |
status | string (active, closed) | yes | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
{
"object": "customer",
"id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"name": "Acme Deliveries Ltd",
"external_reference": "C1042",
"contact": {
"name": "Sam Patel",
"email": "[email protected]",
"phone": null
},
"notes": null,
"is_self": false,
"status": "active",
"livemode": true,
"created_at": "2026-10-01T09:00:00Z",
"updated_at": "2026-10-01T09:00:00Z",
"closed_at": null
}PATCH /partner-api/v1/customers/{id}
Update a customer
Name, reference, contact details and notes. Customers are never deleted through the API.
Key: management key · Scope: customers.write · Idempotency-Key required
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (cus_…) | yes | Public id. |
Request body CustomerUpdateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ||
external_reference | string | Your own customer id. 1–128 printable characters, case-sensitive. | |
contact_name | string | ||
contact_email | string (email) | ||
contact_phone | string | ||
notes | string | Internal notes for your team (never shown to the customer). |
{
"contact_phone": "+44 1473 000000"
}| Status | Body | Meaning |
|---|---|---|
200 | Customer | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Customer)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | yes | Your own id for this customer, unique per partner and mode. |
contact | object | yes | |
notes | string | null | ||
is_self | boolean | yes | The "own fleet" customer of your organisation. |
status | string (active, closed) | yes | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
Fleets
GET /partner-api/v1/fleets
List fleets
Key: management key · Scope: fleets.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
customer_id | query | string (cus_…) | Only fleets of this customer. | |
external_reference | query | string | Exact match on your own reference. | |
status | query | string (pending, provisioning, ready, provisioning_failed, closed) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Fleet)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (flt_…) | yes | |
customer | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | ||
plan_code | string | yes | The plan of every service in this fleet. |
status | string (pending, provisioning, ready, provisioning_failed, closed) | yes | Activations wait until the fleet is ready. |
timezone | string | IANA time zone, e.g. Europe/London. | |
hosted_access_enabled | boolean | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
POST /partner-api/v1/fleets
Create a fleet
Creates the fleet and starts provisioning it on the tracking platform at once (provisioning.operation). The fleet becomes ready within seconds (event fleet.ready; customer.ready for a customer's first fleet). Activations requested earlier wait for it. A fleet created by a key limited to fleets is added to that key. external_reference is unique per partner and mode: a duplicate answers 409 CONFLICT with details.reason = "duplicate_external_reference" and, when your key can see it, details.fleet.
Key: management key · Scope: fleets.write · Idempotency-Key required
Request body FleetCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
customer_id | string (cus_…) | yes | The customer this fleet belongs to (alias: customer). |
name | string | yes | |
plan_code | string | yes | A plan on your rate card (GET /me → plans). |
external_reference | string | Your own id for this fleet. 1–128 printable characters, case-sensitive. | |
timezone | string | IANA time zone (default Europe/London). |
{
"customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"name": "Acme vans",
"plan_code": "pro",
"external_reference": "C1042-main"
}| Status | Body | Meaning |
|---|---|---|
201 | FleetCreated | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (FleetCreated)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (flt_…) | yes | |
customer | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | ||
plan_code | string | yes | The plan of every service in this fleet. |
status | string (pending, provisioning, ready, provisioning_failed, closed) | yes | Activations wait until the fleet is ready. |
timezone | string | IANA time zone, e.g. Europe/London. | |
hosted_access_enabled | boolean | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) | ||
provisioning | object | null | yes | The fleet set-up operation; the event fleet.ready follows when it completes. |
{
"object": "fleet",
"id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"customer": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"name": "Acme vans",
"external_reference": "C1042-main",
"plan_code": "pro",
"status": "provisioning",
"timezone": "Europe/London",
"hosted_access_enabled": false,
"livemode": true,
"created_at": "2026-10-01T09:01:00Z",
"updated_at": "2026-10-01T09:01:00Z",
"closed_at": null,
"provisioning": {
"operation": "op_NPQRSTUVWXYZabcdefghijkm",
"status": "queued"
}
}GET /partner-api/v1/fleets/{id}
Retrieve a fleet
Key: management key · Scope: fleets.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (flt_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Fleet | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Fleet)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (flt_…) | yes | |
customer | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | ||
plan_code | string | yes | The plan of every service in this fleet. |
status | string (pending, provisioning, ready, provisioning_failed, closed) | yes | Activations wait until the fleet is ready. |
timezone | string | IANA time zone, e.g. Europe/London. | |
hosted_access_enabled | boolean | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
PATCH /partner-api/v1/fleets/{id}
Update a fleet
Name, external_reference and timezone only. Change the plan with POST /fleets/{id}/plan-changes; no upstream account fields can be set.
Key: management key · Scope: fleets.write · Idempotency-Key required
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (flt_…) | yes | Public id. |
Request body FleetUpdateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ||
external_reference | string | Your own id for this fleet. 1–128 printable characters, case-sensitive. | |
timezone | string | IANA time zone. |
{
"name": "Acme vans (north)"
}| Status | Body | Meaning |
|---|---|---|
200 | Fleet | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Fleet)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (flt_…) | yes | |
customer | string (cus_…) | yes | |
name | string | yes | |
external_reference | string | null | ||
plan_code | string | yes | The plan of every service in this fleet. |
status | string (pending, provisioning, ready, provisioning_failed, closed) | yes | Activations wait until the fleet is ready. |
timezone | string | IANA time zone, e.g. Europe/London. | |
hosted_access_enabled | boolean | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
closed_at | string | null (date-time) |
POST /partner-api/v1/fleets/{id}/invitations
Invite a hosted tracking user
Only when hosted access is enabled for your account (otherwise 403 PARTNER_ACCESS_REQUIRED with details.feature = "hosted_access"). The invitee receives a Fleetalyse-branded email with a one-time link to their sign-in details (72 hours). Test mode never creates real logins or sends invitations to anyone but you.
Key: management key · Scope: fleets.write · Idempotency-Key required
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (flt_…) | yes | Public id. |
Request body FleetInvitationRequest
| Field | Type | Required | Description |
|---|---|---|---|
email | string (email) | yes | |
name | string |
{
"email": "[email protected]",
"name": "Acme dispatch"
}| Status | Body | Meaning |
|---|---|---|
201 | FleetInvitation | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (FleetInvitation)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
fleet | string (flt_…) | yes | |
email | string | yes | |
name | string | null | ||
status | string (invited, active, blocked) | yes | |
credentials_collected | boolean | The invitee has opened their one-time sign-in details link. | |
link_expires_at | string | null (date-time) | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
operation | string (op_…) | The operation that creates the tracking login. |
Devices
GET /partner-api/v1/device-claims
List device claims
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (pending, approved, rejected, auto_approved) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: DeviceClaim)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (clm_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | |
model | string | null | ||
status | string (pending, approved, rejected, auto_approved) | yes | |
evidence_order_ref | string | null | ||
decision_reason | string | null | Why it was approved or rejected (never names another owner). | |
device | string | null (dev_…) | ||
expires_at | string | null (date-time) | Pending claims lapse at this time. | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
decided_at | string | null (date-time) |
POST /partner-api/v1/device-claims
Claim a device
For supplied or imported hardware Fleetalyse must verify. Evidence is required — knowing an IMEI is not enough: give evidence_text or evidence_order_ref, otherwise 422 INVALID_REQUEST with details.field = "evidence_text". A unit allocated to you by a Fleetalyse hardware order is approved at once (status auto_approved). The decision reason never names another owner.
Key: management key · Scope: devices.write · Idempotency-Key required
Request body DeviceClaimCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
identifier_type | string (imei, serial) | ||
identifier | string | yes | |
manufacturer | string | yes | |
model | string | yes | |
evidence_text | string | Evidence that you own the device. Knowing the IMEI is not enough. | |
evidence_order_ref | string | A Fleetalyse order or invoice reference. | |
fleet_id | string (flt_…) | Fleet to place the device in once approved. | |
sim_provider | string (fleetalyse, own, none) | ||
sim_iccid | string | ||
label | string | Vehicle name shown in your interface. | |
registration_plate | string | ||
vin | string | 17-character VIN. |
{
"identifier": "356307042441013",
"manufacturer": "Teltonika",
"model": "FMC130",
"evidence_order_ref": "FA-100231"
}| Status | Body | Meaning |
|---|---|---|
201 | DeviceClaim | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (DeviceClaim)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (clm_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | |
model | string | null | ||
status | string (pending, approved, rejected, auto_approved) | yes | |
evidence_order_ref | string | null | ||
decision_reason | string | null | Why it was approved or rejected (never names another owner). | |
device | string | null (dev_…) | ||
expires_at | string | null (date-time) | Pending claims lapse at this time. | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
decided_at | string | null (date-time) |
GET /partner-api/v1/device-claims/{id}
Retrieve a device claim
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (clm_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | DeviceClaim | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (DeviceClaim)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (clm_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | |
model | string | null | ||
status | string (pending, approved, rejected, auto_approved) | yes | |
evidence_order_ref | string | null | ||
decision_reason | string | null | Why it was approved or rejected (never names another owner). | |
device | string | null (dev_…) | ||
expires_at | string | null (date-time) | Pending claims lapse at this time. | |
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
decided_at | string | null (date-time) |
GET /partner-api/v1/devices
List devices
Newest first. Keys limited to fleets never see devices without a fleet.
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
identifier | query | string | IMEI or serial (any format; matched on the canonical form). | |
fleet_id | query | string | A flt_ id, or "none" for devices without a fleet. | |
customer_id | query | string (cus_…) | Devices in this customer's fleets. | |
service_status | query | string (none, registered, activation_pending, active, deactivation_pending, inactive, activation_failed) | Current service status. | |
vehicle | query | string (veh_…) | The device currently fitted to this vehicle. | |
connectivity | query | string (online, offline, unknown) | Connectivity state. | |
sim | query | string (fleetalyse, own, none) | SIM provider. | |
ownership | query | string (active, pending_verification, verified, rejected, released, transferred, all) | Ownership state (default active = pending_verification + verified). | |
q | query | string | Free-text search over identifier, label and plate. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Device)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (dev_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | Canonical IMEI (15 digits) or serial number (upper case). |
manufacturer | string | null | ||
model | string | null | ||
source | string (fleetalyse_order, byod, claimed, imported, migrated) | yes | |
ownership | object | yes | |
fleet | string | null (flt_…) | ||
customer | string | null (cus_…) | ||
vehicle | object | null | ||
sim | object | yes | |
connectivity | object | yes | |
service | object | null | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
POST /partner-api/v1/devices
Register a device
Registers a tracker you supply (manufacturer and model from Supported devices). verification.decision tells you whether it is usable at once (verified), being checked (verification_pending) or reviewed by Fleetalyse (review). Refusals are 409 CONFLICT with details.reason: "already_registered" (you already registered it; details.device is your dev_ id), "not_eligible" (held elsewhere — the owner is never named; claim it with evidence if it is yours) or "sim_in_use" (details.field = "sim_iccid": the SIM is fitted to another registered device). Also creates the vehicle (veh_) used by the Tracking API.
Key: management key · Scope: devices.write · Idempotency-Key required
Request body DeviceRegisterRequest
| Field | Type | Required | Description |
|---|---|---|---|
identifier_type | string (imei, serial) | Default imei. | |
identifier | string | yes | IMEI (14 or 15 digits; spaces and dashes removed) or serial number. |
manufacturer | string | yes | As listed in Supported devices. |
model | string | yes | As listed in Supported devices. |
fleet_id | string (flt_…) | Optional fleet to place the device in (alias: fleet). | |
sim_provider | string (fleetalyse, own, none) | ||
sim_iccid | string | ICCID of the SIM fitted in the device. | |
evidence_text | string | Why the device is yours (used when it needs review). | |
evidence_order_ref | string | Order or invoice reference proving purchase. | |
label | string | Vehicle name shown in your interface. | |
registration_plate | string | ||
vin | string | 17-character VIN. |
{
"identifier_type": "imei",
"identifier": "356307042441013",
"manufacturer": "Teltonika",
"model": "FMC130",
"fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"label": "Van 12",
"registration_plate": "AB12 CDE"
}| Status | Body | Meaning |
|---|---|---|
201 | DeviceRegistered | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (DeviceRegistered)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (dev_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | Canonical IMEI (15 digits) or serial number (upper case). |
manufacturer | string | null | ||
model | string | null | ||
source | string (fleetalyse_order, byod, claimed, imported, migrated) | yes | |
ownership | object | yes | |
fleet | string | null (flt_…) | ||
customer | string | null (cus_…) | ||
vehicle | object | null | ||
sim | object | yes | |
connectivity | object | yes | |
service | object | null | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
verification | object | yes |
GET /partner-api/v1/devices/{id}
Retrieve a device
Hardware identity, ownership, fleet, vehicle, SIM, connectivity and the current service — separate fields, never merged.
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (dev_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Device | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Device)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (dev_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | Canonical IMEI (15 digits) or serial number (upper case). |
manufacturer | string | null | ||
model | string | null | ||
source | string (fleetalyse_order, byod, claimed, imported, migrated) | yes | |
ownership | object | yes | |
fleet | string | null (flt_…) | ||
customer | string | null (cus_…) | ||
vehicle | object | null | ||
sim | object | yes | |
connectivity | object | yes | |
service | object | null | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
PATCH /partner-api/v1/devices/{id}
Update a device's vehicle identity
Key: management key · Scope: devices.write · Idempotency-Key required
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (dev_…) | yes | Public id. |
Request body DeviceUpdateRequest
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Vehicle name shown in your interface. | |
registration_plate | string | ||
vin | string | 17-character VIN. |
{
"label": "Van 12",
"registration_plate": "AB12 CDE"
}| Status | Body | Meaning |
|---|---|---|
200 | Device | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Device)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (dev_…) | yes | |
identifier_type | string (imei, serial) | yes | |
identifier | string | yes | Canonical IMEI (15 digits) or serial number (upper case). |
manufacturer | string | null | ||
model | string | null | ||
source | string (fleetalyse_order, byod, claimed, imported, migrated) | yes | |
ownership | object | yes | |
fleet | string | null (flt_…) | ||
customer | string | null (cus_…) | ||
vehicle | object | null | ||
sim | object | yes | |
connectivity | object | yes | |
service | object | null | ||
livemode | boolean | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
Services
POST /partner-api/v1/activations
Activate a tracking service
Activates the fleet's plan on a verified device you own. Asynchronous: 202 means accepted for processing — not that the tracker is active or that anything was charged. Charging starts at the confirmed activation (effective_at). The price comes from your rate card; requests never carry prices or payer ids. Checks your credit exposure (402 BILLING_RESTRICTED / CREDIT_LIMIT_REACHED / PAYMENT_ACTION_REQUIRED). Answers 202 with the operation; 200 when an identical earlier request already finished (created = false). Poll GET /operations/{id} or wait for the webhook.
Key: management key · Scope: services.activate · Idempotency-Key required · Creates charges
Request body ActivationRequest
| Field | Type | Required | Description |
|---|---|---|---|
device_id | string (dev_…) | yes | A verified device you own. |
fleet_id | string (flt_…) | The fleet to activate in (required unless template_id names one). | |
customer_id | string (cus_…) | Optional cross-check: must be the fleet's customer. | |
plan_code | string | Optional; must equal the fleet's plan (plans are per fleet). | |
activate_when | string | as_soon_as_ready (default) or at:<ISO 8601 UTC> for a scheduled start. | |
template_id | string (tpl_…) | Saved activation template (fleet, plan, naming). | |
sim_suspend_on_deactivate | boolean | Suspend a Fleetalyse SIM when this service is later deactivated. | |
external_request_id | string | Your unique id for this intended action (kept permanently): the same id with the same request returns the original operation; with a different request 409 CONFLICT. 1–128 printable characters, case-sensitive. | |
external_order_reference | string | Your order number (not unique; shown on statements). 1–128 printable characters, case-sensitive. |
{
"external_order_reference": "ORDER-1042",
"external_request_id": "ORDER-1042-line-1-activate",
"customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"device_id": "dev_jkmnopqrstuvwxyz12345678",
"plan_code": "pro",
"activate_when": "as_soon_as_ready"
}| Status | Body | Meaning |
|---|---|---|
200 | OperationAccepted | An identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned. |
202 | OperationAccepted | Accepted for processing. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | The device, fleet or plan cannot be used (spec 15.5). Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (OperationAccepted)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. | |
billing | object | yes | |
created | boolean | yes | False when an earlier identical request (Idempotency-Key or external_request_id) already created this operation. |
{
"object": "operation",
"operation_id": "op_VWXYZabcdefghijkmnopqrst",
"type": "activation",
"status": "queued",
"service_id": "svc_cdefghijkmnopqrstuvwxyz1",
"device_id": "dev_jkmnopqrstuvwxyz12345678",
"fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"service_status": "activation_pending",
"billing_status": "not_started",
"effective_at": null,
"scheduled_for": null,
"external_order_reference": "ORDER-1042",
"external_request_id": "ORDER-1042-line-1-activate",
"attempts": 0,
"error": null,
"result": null,
"created_at": "2026-10-01T09:29:58Z",
"updated_at": "2026-10-01T09:29:58Z",
"completed_at": null,
"request_id": "req_TUVWXYZabcdefghijkmnopqr",
"billing": {
"state": "not_started",
"policy": "confirmed_active_time",
"rate_card_version": "rc_4kQ7mZp2XvT9bN3wR8sH6yJd",
"plan_code": "pro",
"full_month_price": {
"amount_minor": 400,
"currency": "GBP",
"tax_mode": "exclusive"
}
},
"created": true
}POST /partner-api/v1/fleets/{id}/plan-changes
Change the plan of a fleet
Changes the plan of every service in the fleet. expected_affected_services must equal the current count (the portal preview shows it); otherwise 409 CONFLICT. Answers 202 with the operation; 200 when an identical earlier request already finished (created = false). Poll GET /operations/{id} or wait for the webhook.
Key: management key · Scope: services.activate · Idempotency-Key required · Creates charges
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (flt_…) | yes | Public id. |
Request body FleetPlanChangeRequest
| Field | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | |
expected_affected_services | integer | yes | The number of services the portal preview showed; a different current number answers 409 CONFLICT. |
external_request_id | string | Your unique id for this intended action (kept permanently): the same id with the same request returns the original operation; with a different request 409 CONFLICT. 1–128 printable characters, case-sensitive. |
{
"plan_code": "pro",
"expected_affected_services": 12
}| Status | Body | Meaning |
|---|---|---|
200 | OperationAccepted | An identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned. |
202 | OperationAccepted | Accepted for processing. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (OperationAccepted)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. | |
billing | object | yes | |
created | boolean | yes | False when an earlier identical request (Idempotency-Key or external_request_id) already created this operation. |
GET /partner-api/v1/services
List services
Service state, billing state and any pending change, newest first.
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
device_id | query | string (dev_…) | Only this device. | |
fleet_id | query | string (flt_…) | Only this fleet. | |
customer_id | query | string (cus_…) | Only this customer. | |
status | query | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Service)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (svc_…) | yes | |
device_id | string (dev_…) | yes | |
fleet_id | string (flt_…) | yes | |
customer_id | string | null (cus_…) | ||
plan_code | string | yes | |
status | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated) | yes | |
desired_state | string (active, inactive) | yes | |
billing | object | yes | |
activated_at | string | null (date-time) | ||
deactivated_at | string | null (date-time) | ||
deactivation_requested_at | string | null (date-time) | ||
scheduled_stop_at | string | null (date-time) | ||
suspension | object | null | ||
sim | object | ||
connectivity | object | ||
pending_operation | object | null | ||
external_order_reference | string | null | ||
version | object | Increase with every accepted change; events carry the same numbers as resource.version. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
GET /partner-api/v1/services/{id}
Retrieve a service
Key: management key · Scope: devices.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (svc_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Service | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Service)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (svc_…) | yes | |
device_id | string (dev_…) | yes | |
fleet_id | string (flt_…) | yes | |
customer_id | string | null (cus_…) | ||
plan_code | string | yes | |
status | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated) | yes | |
desired_state | string (active, inactive) | yes | |
billing | object | yes | |
activated_at | string | null (date-time) | ||
deactivated_at | string | null (date-time) | ||
deactivation_requested_at | string | null (date-time) | ||
scheduled_stop_at | string | null (date-time) | ||
suspension | object | null | ||
sim | object | ||
connectivity | object | ||
pending_operation | object | null | ||
external_order_reference | string | null | ||
version | object | Increase with every accepted change; events carry the same numbers as resource.version. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
POST /partner-api/v1/services/{id}/deactivations
Deactivate a service
Immediate, or scheduled with at. Charging stops at the confirmed deactivation (effective_at of service.deactivation_completed); if confirmation takes longer than the credit threshold after acceptance, the delay is credited. Works while the account is restricted and has its own rate limit (600 a minute per key), separate from the write limit. Deactivating never deletes the device, fleet or history. Answers 202 with the operation; 200 when an identical earlier request already finished (created = false). Poll GET /operations/{id} or wait for the webhook.
Key: management key · Scope: services.deactivate · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (svc_…) | yes | Public id. |
Request body DeactivationRequest
| Field | Type | Required | Description |
|---|---|---|---|
effective | string (immediate, scheduled) | Default immediate. | |
at | string (date-time) | With effective = scheduled: the requested stop time (ISO 8601 UTC). | |
suspend_sim | boolean | Also suspend the Fleetalyse SIM. | |
note | string | Recorded in your audit trail. | |
external_request_id | string | Your unique id for this intended action (kept permanently): the same id with the same request returns the original operation; with a different request 409 CONFLICT. 1–128 printable characters, case-sensitive. | |
external_order_reference | string | Your order number (not unique; shown on statements). 1–128 printable characters, case-sensitive. |
{
"effective": "immediate",
"external_request_id": "ORDER-1042-cancel"
}| Status | Body | Meaning |
|---|---|---|
200 | OperationAccepted | An identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned. |
202 | OperationAccepted | Accepted for processing. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (OperationAccepted)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. | |
billing | object | yes | |
created | boolean | yes | False when an earlier identical request (Idempotency-Key or external_request_id) already created this operation. |
POST /partner-api/v1/services/{id}/plan-changes
Change the plan of a service
Plans are a fleet setting: accepted only when this is the only non-inactive service in its fleet (otherwise 422 PLAN_NOT_AVAILABLE with details.fleet_active_services). The new price applies from the confirmed change. Answers 202 with the operation; 200 when an identical earlier request already finished (created = false). Poll GET /operations/{id} or wait for the webhook.
Key: management key · Scope: services.activate · Idempotency-Key required · Creates charges
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (svc_…) | yes | Public id. |
Request body PlanChangeRequest
| Field | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | |
external_request_id | string | Your unique id for this intended action (kept permanently): the same id with the same request returns the original operation; with a different request 409 CONFLICT. 1–128 printable characters, case-sensitive. |
{
"plan_code": "basic"
}| Status | Body | Meaning |
|---|---|---|
200 | OperationAccepted | An identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned. |
202 | OperationAccepted | Accepted for processing. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (OperationAccepted)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. | |
billing | object | yes | |
created | boolean | yes | False when an earlier identical request (Idempotency-Key or external_request_id) already created this operation. |
POST /partner-api/v1/services/{id}/reactivations
Reactivate a service
Starts a new charging period for an inactive service (no new access fee). Subject to the daily toggle limit (409 CONFLICT, details.reason = "toggle_limit") and your credit exposure. Answers 202 with the operation; 200 when an identical earlier request already finished (created = false). Poll GET /operations/{id} or wait for the webhook.
Key: management key · Scope: services.activate · Idempotency-Key required · Creates charges
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (svc_…) | yes | Public id. |
Request body ReactivationRequest
| Field | Type | Required | Description |
|---|---|---|---|
activate_when | string | as_soon_as_ready (default) or at:<ISO 8601 UTC> for a scheduled start. | |
external_request_id | string | Your unique id for this intended action (kept permanently): the same id with the same request returns the original operation; with a different request 409 CONFLICT. 1–128 printable characters, case-sensitive. | |
external_order_reference | string | Your order number (not unique; shown on statements). 1–128 printable characters, case-sensitive. |
| Status | Body | Meaning |
|---|---|---|
200 | OperationAccepted | An identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned. |
202 | OperationAccepted | Accepted for processing. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (OperationAccepted)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. | |
billing | object | yes | |
created | boolean | yes | False when an earlier identical request (Idempotency-Key or external_request_id) already created this operation. |
Operations
GET /partner-api/v1/operations
List operations
Key: management key · Scope: operations.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | Filter by status. | |
type | query | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration) | Filter by type. | |
service_id | query | string (svc_…) | Only this service. | |
device_id | query | string (dev_…) | Only this device. | |
fleet_id | query | string (flt_…) | Only this fleet. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Operation)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. |
GET /partner-api/v1/operations/{id}
Poll an operation
Status, effective_at and neutral step statuses. Poll with backoff (2, 5, 15, 30 s, then every minute) or use webhooks. requires_attention will not retry by itself.
Key: management key · Scope: operations.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (op_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Operation | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Operation)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. |
{
"object": "operation",
"operation_id": "op_VWXYZabcdefghijkmnopqrst",
"type": "activation",
"status": "completed",
"service_id": "svc_cdefghijkmnopqrstuvwxyz1",
"device_id": "dev_jkmnopqrstuvwxyz12345678",
"fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"service_status": "active",
"billing_status": "accruing",
"effective_at": "2026-10-01T09:30:00Z",
"scheduled_for": null,
"external_order_reference": "ORDER-1042",
"external_request_id": "ORDER-1042-line-1-activate",
"attempts": 1,
"error": null,
"result": null,
"created_at": "2026-10-01T09:29:58Z",
"updated_at": "2026-10-01T09:30:01Z",
"completed_at": "2026-10-01T09:30:01Z",
"request_id": "req_abcdefghijkmnopqrstuvwxy",
"steps": [
{
"step": "service_start",
"label": "Tracking service started",
"status": "completed",
"started_at": "2026-10-01T09:30:00Z",
"finished_at": "2026-10-01T09:30:00Z"
},
{
"step": "confirmation",
"label": "Confirmed with the tracking platform",
"status": "completed",
"started_at": "2026-10-01T09:30:01Z",
"finished_at": "2026-10-01T09:30:01Z"
}
]
}POST /partner-api/v1/operations/{id}/cancellations
Withdraw a scheduled change
Cancels a scheduled or not-yet-started change (for example a scheduled deactivation). A change already running answers 409 CONFLICT. Emits operation.cancelled.
Key: management key · Scope: operations.read · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (op_…) | yes | Public id. |
Request body OperationCancelRequest
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Recorded in your audit trail. |
| Status | Body | Meaning |
|---|---|---|
200 | Operation | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Operation)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
operation_id | string (op_…) | yes | |
type | string (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration, device_registration, migrate_retail_device) | yes | |
status | string (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled) | yes | |
service_id | string | null (svc_…) | ||
device_id | string | null (dev_…) | ||
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
service_status | string | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null) | ||
billing_status | string | null (not_started, accruing, stopped, null) | ||
effective_at | string | null (date-time) | When the change took effect (charging starts or stops at this instant). | |
scheduled_for | string | null (date-time) | ||
external_order_reference | string | null | ||
external_request_id | string | null | ||
attempts | integer | yes | |
error | object | null | ||
result | object | null | Allowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason. | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
completed_at | string | null (date-time) | ||
request_id | string | ||
steps | array of object | Only on GET /operations/{id}. |
Billing
GET /partner-api/v1/billing/invoices
List invoices
Usage, hardware and access-fee invoices. Readable while the account is restricted; limited separately from other reads (600 a minute per key; document links 120 a minute per partner). Needs a key that sees every fleet (fleet-limited keys get 403 or 404).
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated, unpaid) | unpaid = open, payment_failed, action_required or overdue. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Invoice)
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (inv_…) | yes | |
object | string | yes | |
livemode | boolean | yes | |
kind | string (access_fee, usage, hardware) | yes | |
status | string (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated) | yes | |
simulated | boolean | Test-mode invoices are simulated and never charged. | |
number | string | null | ||
currency | string | yes | |
net_minor | integer | Integer minor units (pence). | |
tax_minor | integer | Integer minor units (pence). | |
total_minor | integer | yes | Integer minor units (pence). |
amount_due_minor | integer | yes | Integer minor units (pence). |
refunded_minor | integer | Integer minor units (pence). | |
disputed_minor | integer | Integer minor units (pence). | |
dispute_status | string | null | ||
statement_id | string | null (stm_…) | ||
period | string | null | ||
payment_error | string | null | ||
attempt_count | integer | ||
next_payment_attempt_at | string | null (date-time) | ||
document_available | boolean | GET /billing/invoices/{id}/document can return a link. | |
payable | boolean | ||
created_at | string (date-time) | yes | |
finalised_at | string | null (date-time) | ||
due_at | string | null (date-time) | ||
paid_at | string | null (date-time) | ||
voided_at | string | null (date-time) |
GET /partner-api/v1/billing/invoices/{id}
Retrieve an invoice
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (inv_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Invoice | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Invoice)
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (inv_…) | yes | |
object | string | yes | |
livemode | boolean | yes | |
kind | string (access_fee, usage, hardware) | yes | |
status | string (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated) | yes | |
simulated | boolean | Test-mode invoices are simulated and never charged. | |
number | string | null | ||
currency | string | yes | |
net_minor | integer | Integer minor units (pence). | |
tax_minor | integer | Integer minor units (pence). | |
total_minor | integer | yes | Integer minor units (pence). |
amount_due_minor | integer | yes | Integer minor units (pence). |
refunded_minor | integer | Integer minor units (pence). | |
disputed_minor | integer | Integer minor units (pence). | |
dispute_status | string | null | ||
statement_id | string | null (stm_…) | ||
period | string | null | ||
payment_error | string | null | ||
attempt_count | integer | ||
next_payment_attempt_at | string | null (date-time) | ||
document_available | boolean | GET /billing/invoices/{id}/document can return a link. | |
payable | boolean | ||
created_at | string (date-time) | yes | |
finalised_at | string | null (date-time) | ||
due_at | string | null (date-time) | ||
paid_at | string | null (date-time) | ||
voided_at | string | null (date-time) |
GET /partner-api/v1/billing/invoices/{id}/document
Invoice document link
A fresh, short-lived link to the invoice PDF or payment page, fetched at request time (links are never stored in other responses). 409 CONFLICT for simulated (test-mode) or not yet finalised invoices.
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (inv_…) | yes | Public id. |
format | query | string (pdf, hosted) | pdf (default) or the hosted payment page. |
| Status | Body | Meaning |
|---|---|---|
200 | InvoiceDocument | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (InvoiceDocument)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
invoice_id | string (inv_…) | yes | |
format | string (pdf, hosted) | yes | |
url | string (uri) | yes | Short-lived link issued at request time; request a new one each time. |
retrieved_at | string (date-time) | yes | |
note | string |
GET /partner-api/v1/billing/statements
List statements
Final monthly statements (frozen and later), newest period first. Needs a key that sees every fleet (fleet-limited keys get 403 or 404).
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Statement)
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (stm_…) | yes | |
object | string | yes | |
livemode | boolean | yes | |
simulated | boolean | ||
period | string | yes | |
period_label | string | ||
period_start | string (date-time) | UK midnight of the 1st, in UTC. | |
period_end | string (date-time) | ||
month_seconds | integer | ||
status | string (frozen, invoicing, invoiced, paid, overdue, credited, void, carried_forward, settled_zero) | yes | |
calculation_version | integer | ||
currency | string | yes | |
net_minor | integer | yes | Integer minor units (pence). |
tax_minor | integer | yes | Integer minor units (pence). |
total_minor | integer | yes | Integer minor units (pence). |
vat_rate_bp | integer | null | ||
carried_forward_minor | integer | Integer minor units (pence). | |
adjustments_minor | integer | Integer minor units (pence). | |
delay_credit_minor | integer | Integer minor units (pence). | |
discrepancy_count | integer | ||
snapshot_sha256 | string | null | ||
frozen_at | string | null (date-time) | ||
tax_point_at | string | null (date-time) | ||
invoice_id | string | null (inv_…) | ||
lines | array of StatementSummaryLine | Detail view only. | |
adjustments | array of Adjustment | Detail view only. |
GET /partner-api/v1/billing/statements/{id}
Retrieve a statement
With summary lines per plan and tax basis, and adjustments.
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (stm_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Statement | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Statement)
| Field | Type | Always present | Description |
|---|---|---|---|
id | string (stm_…) | yes | |
object | string | yes | |
livemode | boolean | yes | |
simulated | boolean | ||
period | string | yes | |
period_label | string | ||
period_start | string (date-time) | UK midnight of the 1st, in UTC. | |
period_end | string (date-time) | ||
month_seconds | integer | ||
status | string (frozen, invoicing, invoiced, paid, overdue, credited, void, carried_forward, settled_zero) | yes | |
calculation_version | integer | ||
currency | string | yes | |
net_minor | integer | yes | Integer minor units (pence). |
tax_minor | integer | yes | Integer minor units (pence). |
total_minor | integer | yes | Integer minor units (pence). |
vat_rate_bp | integer | null | ||
carried_forward_minor | integer | Integer minor units (pence). | |
adjustments_minor | integer | Integer minor units (pence). | |
delay_credit_minor | integer | Integer minor units (pence). | |
discrepancy_count | integer | ||
snapshot_sha256 | string | null | ||
frozen_at | string | null (date-time) | ||
tax_point_at | string | null (date-time) | ||
invoice_id | string | null (inv_…) | ||
lines | array of StatementSummaryLine | Detail view only. | |
adjustments | array of Adjustment | Detail view only. |
GET /partner-api/v1/billing/statements/{id}/lines
Per-device statement lines
One line per device and plan: billable seconds, the exact numerator/denominator, price segments, delay credits and your external_order_reference — reproducible to the penny.
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (stm_…) | yes | Public id. |
status | query | string (billed, deferred) | deferred = verified later and billed on a later statement. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: StatementDeviceLine)
| Field | Type | Always present | Description |
|---|---|---|---|
device_id | string (dev_…) | yes | |
device_label | string | null | ||
service_id | string (svc_…) | yes | |
fleet_id | string | null (flt_…) | ||
customer_id | string | null (cus_…) | ||
plan_code | string | yes | |
tax_basis | string (exclusive, inclusive) | ||
status | string (billed, deferred) | yes | |
deferred_reason | string | null | ||
resolution | string | null | ||
billable_seconds | integer | yes | |
numerator | integer | Σ price_minor × seconds over the segments. | |
denominator | integer | Seconds in the month. | |
amount_minor | integer | yes | ROUND_HALF_UP(numerator / denominator). |
delay_credit_minor | integer | Integer minor units (pence). | |
external_order_reference | string | null | ||
segments | array of object |
GET /partner-api/v1/billing/summary
Billing summary
Month-to-date estimate, credit limit, exposure and headroom, unpaid invoices and restriction state. Needs a key that sees every fleet (fleet-limited keys get 403 or 404).
Key: management key · Scope: billing.read
| Status | Body | Meaning |
|---|---|---|
200 | BillingSummary | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (BillingSummary)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
currency | string | yes | |
month_to_date | UsageEstimate | yes | |
credit | object | null | ||
billing_restricted | boolean | yes | |
restricted | boolean | yes | |
unpaid_total_minor | integer | yes | Integer minor units (pence). |
unpaid_invoices | array of Invoice | yes | |
payment_method | object | null | ||
spend_alert_minor | integer | null | ||
latest_statement_id | string | null (stm_…) |
GET /partner-api/v1/billing/usage
Usage by customer
The current month is an estimate until it closes; a closed period returns its statement's usage. include=devices lists estimated device lines of the current month.
Key: management key · Scope: billing.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
period | query | string | YYYY-MM (default: the current UK calendar month). | |
include | query | string (devices) | Add device lines (current month). | |
limit | query | integer | Device lines per page (with include=devices). | |
starting_after | query | string (dev_…) | Continue device lines after this device id. |
| Status | Body | Meaning |
|---|---|---|
200 | Usage | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Usage)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
period | string | yes | |
estimate | boolean | yes | True until the period is closed. |
statement_id | string | null (stm_…) | ||
currency | string | yes | |
by_customer | array of object | yes | |
amount_minor | integer | yes | Integer minor units (pence). |
month_to_date | UsageEstimate | Current period only. | |
devices | array of UsageDeviceLine | With include=devices (current period). | |
devices_has_more | boolean |
GET /partner-api/v1/rate-card
Your rate card
Prices in force (net, per device per full calendar month), announced future versions and any assignment waiting for your acceptance. Never internal costs.
Key: management key · Scope: rate_card.read
| Status | Body | Meaning |
|---|---|---|
200 | RateCard | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (RateCard)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
current | RateCardVersion | null | yes | |
scheduled | array of RateCardVersion | yes | Announced future versions. |
pending_assignment | object | null | ||
charging_rule | string | yes |
Hardware
GET /partner-api/v1/hardware/catalogue
Hardware catalogue
Products with your trade prices, stock, dispatch estimates and delivery options, plus your approved delivery addresses.
Key: management key · Scope: hardware.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
q | query | string | Search name and description. | |
sku | query | string | Exact SKU. | |
model | query | string | Supported tracker model. | |
in_stock | query | string (true, 1) | Only items in stock. |
| Status | Body | Meaning |
|---|---|---|
200 | HardwareCatalogue | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareCatalogue)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
data | array of HardwareProduct | yes | |
has_more | boolean | yes | |
next_cursor | null | ||
delivery_options | array of DeliveryOption | yes | |
ship_to_addresses | array of Address | yes | Approved delivery addresses (keys that see every fleet only). |
GET /partner-api/v1/hardware/orders
List hardware orders
Key: management key · Scope: hardware.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled) | Filter by status. | |
external_order_reference | query | string | Your order number. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: HardwareOrderSummary)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (ord_…) | yes | |
reference | string | ||
status | string (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled) | yes | |
payment_status | string (paid, on_account, awaiting_payment, processing, action_required, payment_failed, overdue, simulated, void, refunded, partially_refunded) | yes | |
livemode | boolean | yes | |
external_order_reference | string | null | ||
currency | string | yes | |
gross_minor | integer | yes | Integer minor units (pence). |
invoice_id | string | null (inv_…) | ||
created_at | string (date-time) | yes | |
dispatched_at | string | null (date-time) | ||
delivered_at | string | null (date-time) |
POST /partner-api/v1/hardware/orders
Order hardware
Accepts an open quote and reserves its stock. The order is paid before dispatch (invoice_immediate) or placed on account when credit is enabled. An expired quote answers 410 QUOTE_EXPIRED; less stock than the quote showed answers 409 CONFLICT with reason stock_changed and details per SKU (request a new quote). Buying hardware never starts a tracking charge: a tracker can be activated once it has been dispatched, unless the order chose activate_before_dispatch.
Key: management key · Scope: hardware.purchase · Idempotency-Key required · Creates charges
Request body HardwareOrderCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
quote_id | string (quo_…) | yes | An open, unexpired quote. |
ship_to | string | Address reference (default: the quote's address). | |
external_order_reference | string | Your order number. 1–128 printable characters, case-sensitive. | |
payment_mode | string (invoice_immediate, credit) | invoice_immediate (default): charged to your saved payment method now; credit: on account when enabled for you. | |
activate_before_dispatch | object | null | Only when enabled for your account. |
{
"quote_id": "quo_rstuvwxyz123456789ABCDEF",
"external_order_reference": "PO-7781"
}| Status | Body | Meaning |
|---|---|---|
201 | HardwareOrder | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
410 | Error | The resource has expired. Codes: QUOTE_EXPIRED. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareOrder)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (ord_…) | yes | |
reference | string | ||
status | string (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled) | yes | |
livemode | boolean | yes | |
quote_id | string (quo_…) | yes | |
external_order_reference | string | null | ||
currency | string | yes | |
totals | object | yes | |
payment | object | yes | |
lines | array of object | yes | |
devices | array of object | Allocated units; each serialised unit is also a device in GET /devices. | |
shipments | array of object | ||
ship_to | Address | null | ||
address_locked | boolean | ||
activate_before_dispatch | object | ||
timeline | array of object | ||
created_at | string (date-time) | yes | |
allocated_at | string | null (date-time) | ||
configured_at | string | null (date-time) | ||
dispatched_at | string | null (date-time) | ||
delivered_at | string | null (date-time) | ||
cancelled_at | string | null (date-time) | ||
cancel_reason | string | null | ||
tracking_charges | string | Buying hardware never starts a tracking charge. |
GET /partner-api/v1/hardware/orders/{id}
Retrieve a hardware order
Payment, allocated serial numbers (each a device), shipments with tracking numbers and a timeline.
Key: management key · Scope: hardware.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (ord_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | HardwareOrder | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareOrder)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (ord_…) | yes | |
reference | string | ||
status | string (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled) | yes | |
livemode | boolean | yes | |
quote_id | string (quo_…) | yes | |
external_order_reference | string | null | ||
currency | string | yes | |
totals | object | yes | |
payment | object | yes | |
lines | array of object | yes | |
devices | array of object | Allocated units; each serialised unit is also a device in GET /devices. | |
shipments | array of object | ||
ship_to | Address | null | ||
address_locked | boolean | ||
activate_before_dispatch | object | ||
timeline | array of object | ||
created_at | string (date-time) | yes | |
allocated_at | string | null (date-time) | ||
configured_at | string | null (date-time) | ||
dispatched_at | string | null (date-time) | ||
delivered_at | string | null (date-time) | ||
cancelled_at | string | null (date-time) | ||
cancel_reason | string | null | ||
tracking_charges | string | Buying hardware never starts a tracking charge. |
POST /partner-api/v1/hardware/quotes
Quote hardware
Confirms price (held until the quote expires), current stock, delivery and expiry. A quote does not hold stock: stock is reserved when you place the order. Problems with lines answer 422 INVALID_REQUEST with details per SKU.
Key: management key · Scope: hardware.quote · Idempotency-Key required
Request body HardwareQuoteCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
lines | array of object | yes | |
delivery_option | string | A delivery option code from the catalogue. | |
ship_to | string | An address reference from the catalogue (default: the first approved address). | |
external_reference | string | Your own reference for this quote. 1–128 printable characters, case-sensitive. |
{
"lines": [
{
"sku": "FMC130",
"quantity": 10
}
],
"delivery_option": "uk_standard"
}| Status | Body | Meaning |
|---|---|---|
201 | HardwareQuote | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
402 | Error | The account is restricted for charge-creating actions, over its credit limit, or a payment needs action. Codes: BILLING_RESTRICTED, CREDIT_LIMIT_REACHED, PAYMENT_ACTION_REQUIRED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareQuote)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (quo_…) | yes | |
status | string (open, accepted, expired, cancelled) | yes | |
livemode | boolean | yes | |
currency | string | yes | |
lines | array of object | yes | |
delivery | object | ||
ship_to | Address | null | ||
totals | object | yes | |
has_backorder | boolean | ||
external_reference | string | null | ||
expires_at | string (date-time) | yes | After this time ordering answers 410 QUOTE_EXPIRED. |
accepted_at | string | null (date-time) | ||
order_id | string | null (ord_…) | ||
created_at | string (date-time) | ||
tracking_charges | string | Buying hardware never starts a tracking charge. |
GET /partner-api/v1/hardware/quotes/{id}
Retrieve a quote
Key: management key · Scope: hardware.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (quo_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | HardwareQuote | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareQuote)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (quo_…) | yes | |
status | string (open, accepted, expired, cancelled) | yes | |
livemode | boolean | yes | |
currency | string | yes | |
lines | array of object | yes | |
delivery | object | ||
ship_to | Address | null | ||
totals | object | yes | |
has_backorder | boolean | ||
external_reference | string | null | ||
expires_at | string (date-time) | yes | After this time ordering answers 410 QUOTE_EXPIRED. |
accepted_at | string | null (date-time) | ||
order_id | string | null (ord_…) | ||
created_at | string (date-time) | ||
tracking_charges | string | Buying hardware never starts a tracking charge. |
POST /partner-api/v1/returns
Request a return
Returns and warranty replacements of Fleetalyse-supplied devices. With service_transfer = transfer the tracking service and vehicle move to the replacement. Available while the account is restricted. Returning hardware never cancels a service by itself.
Key: management key · Scope: hardware.purchase · Idempotency-Key required · Available while restricted
Request body HardwareReturnCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
device_id | string (dev_…) | yes | A device supplied by Fleetalyse. |
reason | string (fault, doa, damaged_in_transit, missing, unwanted, other) | yes | |
symptoms | string | What is wrong (required for faults). | |
preferred_resolution | string (replacement, refund, repair) | ||
service_transfer | string (transfer, none) | transfer (default): move the tracking service to the replacement. | |
external_reference | string | Your own reference. 1–128 printable characters, case-sensitive. |
{
"device_id": "dev_jkmnopqrstuvwxyz12345678",
"reason": "fault",
"symptoms": "No GPS fix since installation.",
"preferred_resolution": "replacement"
}| Status | Body | Meaning |
|---|---|---|
201 | HardwareReturn | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareReturn)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (rma_…) | yes | |
status | string (requested, approved, rejected, received, replaced, refunded, closed) | yes | |
livemode | boolean | yes | |
reason | string | yes | |
symptoms | string | null | ||
preferred_resolution | string | null | ||
resolution | string | null | ||
decision_note | string | null | ||
service_transfer | string (transfer, none) | yes | |
external_reference | string | null | ||
device_id | string | null (dev_…) | ||
device_identifier | string | null | ||
order_id | string | null (ord_…) | ||
order_reference | string | null | ||
replacement | object | null | ||
service_transfer_requested | boolean | ||
refund_net_minor | integer | Integer minor units (pence). | |
created_at | string (date-time) | yes | |
decided_at | string | null (date-time) | ||
received_at | string | null (date-time) | ||
refunded_at | string | null (date-time) | ||
closed_at | string | null (date-time) | ||
note | string |
GET /partner-api/v1/returns/{id}
Retrieve a return
Key: management key · Scope: hardware.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (rma_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | HardwareReturn | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (HardwareReturn)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (rma_…) | yes | |
status | string (requested, approved, rejected, received, replaced, refunded, closed) | yes | |
livemode | boolean | yes | |
reason | string | yes | |
symptoms | string | null | ||
preferred_resolution | string | null | ||
resolution | string | null | ||
decision_note | string | null | ||
service_transfer | string (transfer, none) | yes | |
external_reference | string | null | ||
device_id | string | null (dev_…) | ||
device_identifier | string | null | ||
order_id | string | null (ord_…) | ||
order_reference | string | null | ||
replacement | object | null | ||
service_transfer_requested | boolean | ||
refund_net_minor | integer | Integer minor units (pence). | |
created_at | string (date-time) | yes | |
decided_at | string | null (date-time) | ||
received_at | string | null (date-time) | ||
refunded_at | string | null (date-time) | ||
closed_at | string | null (date-time) | ||
note | string |
API credentials
GET /partner-api/v1/credentials
List API keys
Keys of either class. An API key sees the keys it created (and keys those keys created); newest first.
Key: management key · Scope: credentials.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (all, active, revoked, expired) | Filter by status. | |
class | query | string (management, tracking) | Filter by key class. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Credential)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes |
POST /partner-api/v1/credentials
Create an API key
The new key can never exceed its creator: same or fewer scopes, a subset of the fleets, an expiry no later than the creator's and an IP allowlist inside it; always the creator's mode. The secret is returned once (an idempotent replay returns "secret": null). 409 CONFLICT with details.reason "credential_limit" when the account already has the most active keys allowed in this mode.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
Request body CredentialCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | A name you recognise, e.g. the system that uses it. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | Same or fewer than the creating key. Tracking keys: tracking.read (default). | |
fleet_scope_mode | string (selected, all_current, all_current_and_future) | Default: selected when fleet_ids is given; otherwise all_current for keys that see every fleet, or the creator's own fleets. all_current_and_future only by the owner in the portal. | |
fleet_ids | array of string (flt_…) | With fleet_scope_mode selected. | |
expires_at | string | null (date-time) | Optional; never later than the creating key's expiry. | |
ip_allowlist | array of string | null | Addresses or CIDR ranges; inside the creator's allowlist. | |
class | string (management, tracking) | yes |
{
"name": "Warehouse app",
"class": "management",
"scopes": [
"devices.read",
"devices.write"
],
"fleet_scope_mode": "all_current"
}| Status | Body | Meaning |
|---|---|---|
201 | CredentialWithSecret | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialWithSecret)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes | |
secret | string | null | yes | Shown once. An idempotent replay returns null. |
{
"object": "credential",
"id": "key_4Hq9sT2vW7xY3zB5cD8fG1jK",
"class": "tracking",
"name": "Acme portal feed",
"livemode": true,
"key_prefix": "ftk_live_7Hk2Lm9",
"status": "active",
"scopes": [
"tracking.read"
],
"fleet_scope": {
"mode": "selected",
"fleet_ids": [
"flt_2Nw8Pq4Rs6Tu8Vx1Yz3Ab5Cd"
]
},
"ip_allowlist": [
"203.0.113.10"
],
"expires_at": "2027-10-01T00:00:00Z",
"rotation": {
"rotated_from": null,
"replaced_by": null,
"valid_until": null
},
"revoked_at": null,
"revoked_reason": null,
"created_by": {
"type": "credential",
"id": "key_9Kd3Fg5Hj7Lm2Np4Qr6St8Uv",
"name": "Order system"
},
"last_used_at": null,
"last_used_ip": null,
"created_at": "2026-10-01T09:30:00Z",
"secret": "ftk_live_7Hk2Lm9Xa8bQ3mN5pR7sT9vW2yZ4cD6eF8gH1jK3m"
}GET /partner-api/v1/credentials/{id}
Retrieve an API key
Key: management key · Scope: credentials.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Credential | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Credential)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes |
DELETE /partner-api/v1/credentials/{id}
Revoke an API key
Revokes the key, every key it created and a predecessor still in its rotation overlap; disables webhook endpoints they registered. Takes effect at once (within 60 s including cached data). Never cancels devices or services. Revoking an already revoked key returns it with zero counts.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
Request body CredentialRevokeRequest
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Recorded in your audit trail. |
| Status | Body | Meaning |
|---|---|---|
200 | CredentialRevokeResponse | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialRevokeResponse)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes | |
cascade | object | yes |
POST /partner-api/v1/credentials/{id}/rotate
Rotate an API key
Issues a new key with the same or narrower access; the old secret keeps working for overlap_seconds (default 24 h). created_resources decides what happens to the keys the old key created and the webhook endpoints it registered: "transfer" moves them to the new key, "revoke" revokes them with the old key, which stops at once (use it for a leaked key; the default when overlap_seconds is 0). 409 CONFLICT when the key is revoked, expired or already rotated.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
Request body CredentialRotateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Defaults to the old key's name. | |
scopes | array of string | Same or fewer than the old key. | |
fleet_ids | array of string (flt_…) | A subset of the old key's fleets. | |
expires_at | string | null (date-time) | No later than the old key's expiry. | |
ip_allowlist | array of string | null | ||
overlap_seconds | integer | How long the old secret keeps working. 0 revokes it at once. Defaults to 0 with created_resources "revoke" (any other value is refused). | |
created_resources | string (transfer, revoke) | Keys the old key created and webhook endpoints it registered: "transfer" moves them to the new key (any beyond its access are revoked or disabled); "revoke" revokes and disables them with the old key, which stops at once — use it for a key that may have leaked. Default: "revoke" when overlap_seconds is 0, otherwise "transfer". |
{
"overlap_seconds": 3600
}| Status | Body | Meaning |
|---|---|---|
201 | CredentialRotateResponse | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialRotateResponse)
| Field | Type | Always present | Description |
|---|---|---|---|
previous_key | object | yes | |
created_resources | object | yes |
GET /partner-api/v1/tracking-credentials
List tracking-data keys
Tracking-data keys only (spec 15.2). An API key sees the keys it created (and keys those keys created); newest first.
Key: management key · Scope: credentials.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (all, active, revoked, expired) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Credential)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes |
POST /partner-api/v1/tracking-credentials
Create a tracking-data key
The new key can never exceed its creator: same or fewer scopes, a subset of the fleets, an expiry no later than the creator's and an IP allowlist inside it; always the creator's mode. The secret is returned once (an idempotent replay returns "secret": null). 409 CONFLICT with details.reason "credential_limit" when the account already has the most active keys allowed in this mode.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
Request body TrackingCredentialCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | A name you recognise, e.g. the system that uses it. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | Same or fewer than the creating key. Tracking keys: tracking.read (default). | |
fleet_scope_mode | string (selected, all_current, all_current_and_future) | Default: selected when fleet_ids is given; otherwise all_current for keys that see every fleet, or the creator's own fleets. all_current_and_future only by the owner in the portal. | |
fleet_ids | array of string (flt_…) | With fleet_scope_mode selected. | |
expires_at | string | null (date-time) | Optional; never later than the creating key's expiry. | |
ip_allowlist | array of string | null | Addresses or CIDR ranges; inside the creator's allowlist. |
{
"name": "Acme portal feed",
"fleet_ids": [
"flt_2Nw8Pq4Rs6Tu8Vx1Yz3Ab5Cd"
],
"expires_at": "2027-10-01T00:00:00Z",
"ip_allowlist": [
"203.0.113.10"
]
}| Status | Body | Meaning |
|---|---|---|
201 | CredentialWithSecret | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialWithSecret)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes | |
secret | string | null | yes | Shown once. An idempotent replay returns null. |
{
"object": "credential",
"id": "key_4Hq9sT2vW7xY3zB5cD8fG1jK",
"class": "tracking",
"name": "Acme portal feed",
"livemode": true,
"key_prefix": "ftk_live_7Hk2Lm9",
"status": "active",
"scopes": [
"tracking.read"
],
"fleet_scope": {
"mode": "selected",
"fleet_ids": [
"flt_2Nw8Pq4Rs6Tu8Vx1Yz3Ab5Cd"
]
},
"ip_allowlist": [
"203.0.113.10"
],
"expires_at": "2027-10-01T00:00:00Z",
"rotation": {
"rotated_from": null,
"replaced_by": null,
"valid_until": null
},
"revoked_at": null,
"revoked_reason": null,
"created_by": {
"type": "credential",
"id": "key_9Kd3Fg5Hj7Lm2Np4Qr6St8Uv",
"name": "Order system"
},
"last_used_at": null,
"last_used_ip": null,
"created_at": "2026-10-01T09:30:00Z",
"secret": "ftk_live_7Hk2Lm9Xa8bQ3mN5pR7sT9vW2yZ4cD6eF8gH1jK3m"
}GET /partner-api/v1/tracking-credentials/{id}
Retrieve a tracking-data key
Key: management key · Scope: credentials.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Credential | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Credential)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes |
DELETE /partner-api/v1/tracking-credentials/{id}
Revoke a tracking-data key
Revokes the key, every key it created and a predecessor still in its rotation overlap; disables webhook endpoints they registered. Takes effect at once (within 60 s including cached data). Never cancels devices or services. Revoking an already revoked key returns it with zero counts.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
Request body CredentialRevokeRequest
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | Recorded in your audit trail. |
| Status | Body | Meaning |
|---|---|---|
200 | CredentialRevokeResponse | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialRevokeResponse)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (key_…) | yes | |
class | string (management, tracking) | yes | |
name | string | yes | |
livemode | boolean | yes | |
key_prefix | string | yes | The first 16 characters of the secret, safe to display. |
status | string (active, expiring, expired, revoked) | yes | expiring: within the warning period of expires_at, or rotated and still inside its overlap. |
scopes | array of string (customers.read, customers.write, fleets.read, fleets.write, devices.read, devices.write, services.activate, services.deactivate, operations.read, hardware.read, hardware.quote, hardware.purchase, billing.read, rate_card.read, webhooks.manage, credentials.manage, tracking.read) | yes | |
fleet_scope | object | yes | |
ip_allowlist | array of string | null | ||
expires_at | string | null (date-time) | ||
rotation | object | ||
revoked_at | string | null (date-time) | ||
revoked_reason | string | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null) | ||
created_by | CreatedBy | ||
last_used_at | string | null (date-time) | Updated at most once a minute. | |
last_used_ip | string | null | ||
created_at | string (date-time) | yes | |
cascade | object | yes |
POST /partner-api/v1/tracking-credentials/{id}/rotate
Rotate a tracking-data key
Issues a new key with the same or narrower access; the old secret keeps working for overlap_seconds (default 24 h). created_resources decides what happens to the keys the old key created and the webhook endpoints it registered: "transfer" moves them to the new key, "revoke" revokes them with the old key, which stops at once (use it for a leaked key; the default when overlap_seconds is 0). 409 CONFLICT when the key is revoked, expired or already rotated.
Key: management key · Scope: credentials.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (key_…) | yes | Public id. |
Request body CredentialRotateRequest
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Defaults to the old key's name. | |
scopes | array of string | Same or fewer than the old key. | |
fleet_ids | array of string (flt_…) | A subset of the old key's fleets. | |
expires_at | string | null (date-time) | No later than the old key's expiry. | |
ip_allowlist | array of string | null | ||
overlap_seconds | integer | How long the old secret keeps working. 0 revokes it at once. Defaults to 0 with created_resources "revoke" (any other value is refused). | |
created_resources | string (transfer, revoke) | Keys the old key created and webhook endpoints it registered: "transfer" moves them to the new key (any beyond its access are revoked or disabled); "revoke" revokes and disables them with the old key, which stops at once — use it for a key that may have leaked. Default: "revoke" when overlap_seconds is 0, otherwise "transfer". |
{
"overlap_seconds": 3600
}| Status | Body | Meaning |
|---|---|---|
201 | CredentialRotateResponse | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (CredentialRotateResponse)
| Field | Type | Always present | Description |
|---|---|---|---|
previous_key | object | yes | |
created_resources | object | yes |
Webhooks
GET /partner-api/v1/webhook-endpoints
List webhook endpoints
Endpoints the key may manage: within its fleets and only those whose event types it could subscribe to.
Key: management key · Scope: webhooks.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
status | query | string (pending, active, disabled) | Filter by status. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: WebhookEndpoint)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
POST /partner-api/v1/webhook-endpoints
Register a webhook endpoint
The URL must be https on port 443 or 8443 and resolve only to public addresses. Event types are limited to those whose scope the key holds; endpoints limited to fleets receive fleet events only. The endpoint stays pending until POST /webhook-endpoints/{id}/test is answered with 2xx. The signing secret is returned once. At most 20 endpoints per mode.
Key: management key · Scope: webhooks.manage · Idempotency-Key required · Available while restricted
Request body WebhookEndpointCreateRequest
| Field | Type | Required | Description |
|---|---|---|---|
url | string (uri) | yes | https, port 443 or 8443, public address only; redirects are not followed. |
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched, *) | string | yes | "*" = every type the creating key may receive (fleet events only for fleet-limited endpoints). |
fleet_ids | array of string (flt_…) | null | Omit for all fleets (partner-wide keys only). | |
description | string |
{
"url": "https://example.com/webhooks/fleetalyse",
"event_types": [
"service.activation_completed",
"service.deactivation_completed"
],
"description": "Main CRM"
}| Status | Body | Meaning |
|---|---|---|
201 | WebhookEndpointWithSecret | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookEndpointWithSecret)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
secret | string | null | yes | Signing secret, shown once. An idempotent replay returns null. |
{
"object": "webhook_endpoint",
"id": "we_6Tq2Wr8Yu4Io1Pa3Sd5Fg7Hj",
"url": "https://example.com/webhooks/fleetalyse",
"description": "Main CRM",
"livemode": true,
"status": "pending",
"disabled_reason": null,
"event_types": [
"service.activation_completed",
"service.deactivation_completed"
],
"fleet_scope": {
"mode": "all",
"fleet_ids": null
},
"secret_prefix": "whsec_Hq7Kd2",
"previous_secret_valid_until": null,
"health": {
"verified_at": null,
"last_success_at": null,
"last_failure_at": null,
"failing_since": null,
"consecutive_failures": 0
},
"created_by": {
"type": "credential",
"id": "key_9Kd3Fg5Hj7Lm2Np4Qr6St8Uv",
"name": "Order system"
},
"created_at": "2026-10-01T09:30:00Z",
"updated_at": "2026-10-01T09:30:00Z",
"secret": "whsec_Hq7Kd2Lp9Zx4Cv6Bn8Mq1Wr3Ty5Ui7Op9As2Df4Gh6J"
}GET /partner-api/v1/webhook-endpoints/{id}
Retrieve a webhook endpoint
Key: management key · Scope: webhooks.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | WebhookEndpoint | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookEndpoint)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
PATCH /partner-api/v1/webhook-endpoints/{id}
Update a webhook endpoint
Change the URL (back to pending until a new test event succeeds), description, event types or fleets, or enable/disable it. Unknown fields are rejected.
Key: management key · Scope: webhooks.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
Request body WebhookEndpointUpdateRequest
| Field | Type | Required | Description |
|---|---|---|---|
url | string (uri) | Returns the endpoint to pending until a new test event succeeds. | |
description | string | null | ||
event_types | array of string | ||
fleet_ids | array of string (flt_…) | null | ||
enabled | boolean | false disables; true returns a disabled endpoint to pending. |
{
"enabled": false
}| Status | Body | Meaning |
|---|---|---|
200 | WebhookEndpoint | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookEndpoint)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
DELETE /partner-api/v1/webhook-endpoints/{id}
Delete a webhook endpoint
Stops every delivery and destroys the signing secret. The endpoint is returned with status "deleted".
Key: management key · Scope: webhooks.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | WebhookEndpoint | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookEndpoint)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) |
GET /partner-api/v1/webhook-endpoints/{id}/deliveries
List deliveries to an endpoint
The delivery log: status, attempts, last HTTP status, a redacted excerpt of your response and the next attempt. No secrets.
Key: management key · Scope: webhooks.manage
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
status | query | string (pending, delivering, succeeded, failed, abandoned) | Filter by status. | |
event_id | query | string (evt_…) | Only deliveries of this event. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: WebhookDelivery)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
event_id | string (evt_…) | yes | |
event_type | string | yes | |
endpoint_id | string (we_…) | yes | |
status | string (pending, delivering, succeeded, failed, abandoned) | yes | failed = will be retried at next_attempt_at; abandoned = no more attempts. |
attempts | integer | yes | |
last_http_status | integer | null | ||
last_error | string | null | ||
response_excerpt | string | null | First 500 characters of your response, with anything that looks like a secret masked. | |
next_attempt_at | string | null (date-time) | ||
delivered_at | string | null (date-time) | ||
replay | boolean | ||
created_at | string (date-time) |
POST /partner-api/v1/webhook-endpoints/{id}/rotate-secret
Rotate the signing secret
Returns a new secret once. During overlap_seconds every request is signed with both secrets (two v1 values).
Key: management key · Scope: webhooks.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
Request body WebhookRotateSecretRequest
| Field | Type | Required | Description |
|---|---|---|---|
overlap_seconds | integer | How long the previous secret still signs every request (second v1 value). |
| Status | Body | Meaning |
|---|---|---|
200 | WebhookEndpointWithSecret | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookEndpointWithSecret)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (we_…) | yes | |
url | string (uri) | yes | |
description | string | null | ||
livemode | boolean | yes | |
status | string (pending, active, disabled, deleted) | yes | pending until the signed test event is answered with 2xx. |
disabled_reason | string | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null) | ||
event_types | array of string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched) | yes | |
fleet_scope | object | yes | |
secret_prefix | string | null | First characters of the signing secret. | |
previous_secret_valid_until | string | null (date-time) | During a rotation overlap, requests carry a second v1 signature with the previous secret until this time. | |
health | object | ||
created_by | CreatedBy | ||
created_at | string (date-time) | yes | |
updated_at | string (date-time) | ||
secret | string | null | yes | Signing secret, shown once. An idempotent replay returns null. |
POST /partner-api/v1/webhook-endpoints/{id}/test
Send a signed test event
Posts a signed test.ping event now and reports the result. A 2xx answer activates a pending endpoint. No Idempotency-Key needed; limited to 20 per endpoint per hour.
Key: management key · Scope: webhooks.manage · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (we_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | WebhookTestResult | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (WebhookTestResult)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
succeeded | boolean | yes | |
http_status | integer | null | ||
error | string | null | ||
response_excerpt | string | null | ||
duration_ms | integer | ||
event_id | string (evt_…) | yes | |
endpoint | WebhookEndpoint | yes |
Events
GET /partner-api/v1/events
List events
Events the key may see (type scope held, fleet in scope; partner-level events for keys that see every fleet), newest first. Use it to catch up after downtime.
Key: management key
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
type | query | string | Only this event type. | |
created_after | query | string (date-time) | Inclusive lower bound (ISO 8601 with offset). | |
created_before | query | string (date-time) | Exclusive upper bound. | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Event)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (evt_…) | yes | Stable across retries and replays — deduplicate on it. |
type | string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched, test.ping) | yes | |
schema_version | string | yes | |
created_at | string (date-time) | yes | |
livemode | boolean | yes | |
resource | object | null | yes | |
data | object | yes | The resource snapshot of the emitting endpoint family (ids are public ids). |
GET /partner-api/v1/events/{id}
Retrieve an event
Key: management key
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (evt_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Event | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Event)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (evt_…) | yes | Stable across retries and replays — deduplicate on it. |
type | string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched, test.ping) | yes | |
schema_version | string | yes | |
created_at | string (date-time) | yes | |
livemode | boolean | yes | |
resource | object | null | yes | |
data | object | yes | The resource snapshot of the emitting endpoint family (ids are public ids). |
{
"object": "event",
"id": "evt_example001Xa8bQ3mN5pR7s",
"type": "service.activation_completed",
"schema_version": "1",
"created_at": "2026-10-01T09:30:02Z",
"livemode": true,
"resource": {
"type": "service",
"id": "svc_example01Xa8bQ3mN5pR7sT",
"version": 3
},
"data": {
"customer_id": "cus_example_a",
"fleet_id": "flt_example_a",
"device_id": "dev_example_01",
"service_id": "svc_example_01",
"operation_id": "op_example_1042",
"external_order_reference": "ORDER-1042",
"effective_at": "2026-10-01T09:30:00Z"
}
}POST /partner-api/v1/events/{id}/replay
Replay an event
Queues a new delivery of the SAME event (same id and body, header Fleetalyse-Replay: true) to one endpoint or to every active endpoint you manage that received it. At most 20 replays per endpoint per hour (429). Test events cannot be replayed.
Key: management key · Scope: webhooks.manage · Idempotency-Key required · Available while restricted
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (evt_…) | yes | Public id. |
Request body EventReplayRequest
| Field | Type | Required | Description |
|---|---|---|---|
endpoint_id | string (we_…) | Omit to replay to every active endpoint you manage that received the event. |
| Status | Body | Meaning |
|---|---|---|
202 | EventReplay | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (EventReplay)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
event_id | string (evt_…) | yes | |
deliveries | array of WebhookDelivery | yes |
Notices
GET /partner-api/v1/notices
Service notices
Incidents and planned maintenance that apply to your account: active now, plus maintenance starting within upcoming_days.
Key: management key
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
upcoming_days | query | integer | Include maintenance starting within this many days. |
| Status | Body | Meaning |
|---|---|---|
200 | NoticeList | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (NoticeList)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
data | array of Notice | yes | |
has_more | boolean | yes |
Tracking API
GET /tracking-api/v1/ping
Check a tracking-data key
Key: tracking-data key
| Status | Body | Meaning |
|---|---|---|
200 | Ping | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Ping)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
ok | boolean | yes | |
livemode | boolean | yes | |
partner | string (ptn_…) | yes | |
credential | string | null (key_…) | ||
credential_class | string (management, tracking) | ||
scopes | array of string | ||
fleet_scope | string (all, selected) | ||
time | string (date-time) | ||
request_id | string |
GET /tracking-api/v1/vehicles
List vehicles
Vehicles in the key's fleets, newest first, including vehicles whose service is not active (with service_status and no position).
Key: tracking-data key · Scope: tracking.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
fleet_id | query | string (flt_…) | Only this fleet. | |
service_status | query | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none, tracking) | tracking = active or deactivation_pending; none = no service. | |
include | query | string (position) | Add last_position (only for vehicles whose service is active). | |
limit | query | integer | Page size (1–200, default 50). | |
cursor | query | string | next_cursor of the previous page. Bound to the key, the endpoint and the filters. |
| Status | Body | Meaning |
|---|---|---|
200 | ListEnvelope | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (each item in data: Vehicle)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (veh_…) | yes | |
label | string | null | ||
registration_plate | string | null | ||
vin | string | null | ||
fleet_id | string | null (flt_…) | yes | |
device_id | string | null (dev_…) | ||
service | object | null | ||
service_status | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none) | yes | |
tracking | object | yes | |
last_position | PositionFields | null | ||
livemode | boolean | ||
created_at | string (date-time) | yes |
GET /tracking-api/v1/vehicles/{id}
Retrieve a vehicle
Key: tracking-data key · Scope: tracking.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (veh_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Vehicle | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Vehicle)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
id | string (veh_…) | yes | |
label | string | null | ||
registration_plate | string | null | ||
vin | string | null | ||
fleet_id | string | null (flt_…) | yes | |
device_id | string | null (dev_…) | ||
service | object | null | ||
service_status | string (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none) | yes | |
tracking | object | yes | |
last_position | PositionFields | null | ||
livemode | boolean | ||
created_at | string (date-time) | yes |
GET /tracking-api/v1/vehicles/{id}/journeys
Journeys of a vehicle
At most 31 days per request. Clipped to the periods the vehicle's service was active under your account, the plan's history_days and the time the device was fitted; the served periods are listed in windows. A journey is returned when it starts and ends inside a window. Distances in metres, speeds in km/h.
Key: tracking-data key · Scope: tracking.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (veh_…) | yes | Public id. |
from | query | string (date-time) | yes | Start (ISO 8601 with offset). |
till | query | string (date-time) | yes | End; at most 31 days after from. |
include_stops | query | boolean | Also return stops between journeys. |
| Status | Body | Meaning |
|---|---|---|
200 | JourneyList | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (JourneyList)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
vehicle_id | string (veh_…) | yes | |
from | string (date-time) | yes | |
till | string (date-time) | yes | |
windows | array of object | yes | Entitled periods served (active service × plan history × device fitted). |
clipped | boolean | yes | |
history_days | integer | null | ||
data | array of Journey | yes | |
has_more | boolean | ||
simulated | boolean |
GET /tracking-api/v1/vehicles/{id}/position
Latest position of a vehicle
Only while the vehicle's service is active or deactivation_pending; otherwise 409 SERVICE_INACTIVE with details.service_status. Cached for at most 30 s per key. Missing values are null.
Key: tracking-data key · Scope: tracking.read
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (veh_…) | yes | Public id. |
| Status | Body | Meaning |
|---|---|---|
200 | Position | Success. |
400 | Error | The request is malformed, a header or query value is invalid, or the body is too large / not JSON (413, 415). Codes: INVALID_REQUEST, TEST_MODE_MISMATCH. |
401 | Error | Missing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED. |
403 | Error | The key lacks a scope or is the wrong class for this API, or the partner account is not active. Codes: INSUFFICIENT_SCOPE, PARTNER_ACCESS_REQUIRED. |
404 | Error | Unknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND. |
409 | Error | Idempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE. |
422 | Error | Well-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE. |
429 | Error | Too many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED. |
500 | Error | Unexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR. |
503 | Error | Temporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE. |
Response fields (Position)
| Field | Type | Always present | Description |
|---|---|---|---|
object | string | yes | |
vehicle_id | string (veh_…) | yes | |
device_id | string | null (dev_…) | ||
recorded_at | string | null (date-time) | yes | When the device recorded the position (UTC). |
latitude | number | null | yes | WGS84 decimal degrees. |
longitude | number | null | yes | WGS84 decimal degrees. |
speed_kmh | integer | null | km/h | |
heading_deg | integer | null | Degrees clockwise from north. | |
movement | string (driving, standing, no_gps, no_data, unknown) | yes | |
age_seconds | integer | null | ||
stale | boolean | yes | Older than 10 minutes (or no data). |
retrieved_at | string (date-time) | yes | |
max_cache_age_seconds | integer | ||
simulated | boolean | yes | True in test mode. |
{
"object": "position",
"vehicle_id": "veh_7Kq2Wx9Zc4Vb6Nm8Lk1Jh3Gf",
"device_id": "dev_example01Xa8bQ3mN5pR7s",
"recorded_at": "2026-10-01T09:29:41Z",
"latitude": 52.056721,
"longitude": 1.148203,
"speed_kmh": 46,
"heading_deg": 212,
"movement": "driving",
"age_seconds": 19,
"stale": false,
"retrieved_at": "2026-10-01T09:30:00Z",
"max_cache_age_seconds": 30,
"simulated": false
}Webhook requests we send you
POST your endpoint URL
An event delivered to your endpoint
Fleetalyse POSTs each event (JSON, UTF-8) to every active endpoint that subscribes to its type and covers its fleet. Verify Fleetalyse-Signature over the RAW body before parsing: HMAC-SHA256 with your whsec_ secret of "<t>.<raw body>", hex; accept when any v1 value matches and |now − t| ≤ 300 s. During a secret rotation the header carries one v1 per valid secret.
Delivery is at least once: deduplicate on the event id (Fleetalyse-Event-Id), tolerate out-of-order events and re-read the resource (resource.id, resource.version) when order matters. Answer any 2xx within 10 seconds; anything else (or a timeout) is retried with backoff and jitter (30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, then every 6 h) for 72 hours. An endpoint that fails continuously for 72 hours is disabled and its owner emailed. Redirects are never followed. Replays keep the event id and add Fleetalyse-Replay: true.
Headers
| Header | Type | Always | Meaning |
|---|---|---|---|
Fleetalyse-Signature | string | yes | t=<unix seconds>,v1=<hex HMAC-SHA256>[,v1=<previous secret>] |
Fleetalyse-Event-Id | string (evt_…) | yes | The event id (same as the body id); stable across retries and replays. |
Fleetalyse-Event-Type | string | yes | The event type. |
Fleetalyse-Delivery-Attempt | integer | yes | Attempt number of this delivery, from 1. |
Fleetalyse-Mode | string (live, test) | yes | live or test (endpoints only receive events of their own mode). |
Fleetalyse-Replay | string (true) | Present on manual replays. |
Body WebhookEventPayload
| Field | Type | Required | Description |
|---|---|---|---|
id | string (evt_…) | yes | Stable across retries and replays — deduplicate on it. |
type | string (customer.ready, customer.provisioning_failed, fleet.ready, fleet.provisioning_failed, fleet.plan_changed, service.activation_completed, service.activation_failed, service.deactivation_completed, service.deactivation_failed, service.reactivation_completed, service.plan_changed, operation.requires_attention, operation.cancelled, invoice.finalised, invoice.paid, invoice.payment_failed, invoice.payment_action_required, partner.billing_restricted, partner.billing_restored, hardware.order_dispatched, test.ping) | yes | |
schema_version | string | yes | |
created_at | string (date-time) | yes | |
livemode | boolean | yes | |
resource | object | null | yes | |
data | object | yes |
{
"id": "evt_YZabcdefghijkmnopqrstuvw",
"type": "service.activation_completed",
"schema_version": "1",
"created_at": "2026-10-01T09:30:02Z",
"livemode": true,
"resource": {
"type": "service",
"id": "svc_cdefghijkmnopqrstuvwxyz1",
"version": 1
},
"data": {
"service_id": "svc_cdefghijkmnopqrstuvwxyz1",
"device_id": "dev_jkmnopqrstuvwxyz12345678",
"fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
"customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
"operation_id": "op_VWXYZabcdefghijkmnopqrst",
"plan_code": "pro",
"status": "active",
"billing_status": "accruing",
"external_order_reference": "ORDER-1042",
"effective_at": "2026-10-01T09:30:00Z"
}
}| Your answer | What happens |
|---|---|
2XX | Received. Answer quickly and process the event afterwards. |
default | Any other status, a redirect or no answer within 10 s: the delivery is retried. |