Skip to main content
Fleetalyse
Partner API & Tracking API

API reference

Every endpoint, generated from the OpenAPI document.

The Fleetalyse Partner Programme is running as a pilot. The API documented here is available to approved partners; you can build against test mode as soon as your partner account is open. About partnering with Fleetalyse

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

StatusBodyMeaning
200PartnerSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Partner)
FieldTypeAlways presentDescription
objectstringyes
idstring (ptn_…)yes
livemodebooleanyes
modestring (live, test)yes
namestringyesTrading name (or legal name).
legal_namestring
entitlementobjectyes
capabilitiesobjectyes
limitsobjectyes
plansarray of objectyes
credentialobject | nullThe API key making the request.
request_idstring

GET /partner-api/v1/openapi.json

This OpenAPI document

Public, no authentication.

Key: none (public)

StatusBodyMeaning
200objectThe OpenAPI 3.1 document.
503ErrorTemporarily 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

StatusBodyMeaning
200PingSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Ping)
FieldTypeAlways presentDescription
objectstringyes
okbooleanyes
livemodebooleanyes
partnerstring (ptn_…)yes
credentialstring | null (key_…)
credential_classstring (management, tracking)
scopesarray of string
fleet_scopestring (all, selected)
timestring (date-time)
request_idstring

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

ParameterInTypeRequiredDescription
external_referencequerystringExact match on your own reference (case-sensitive).
statusquerystring (active, closed)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Customer)
FieldTypeAlways presentDescription
objectstringyes
idstring (cus_…)yes
namestringyes
external_referencestring | nullyesYour own id for this customer, unique per partner and mode.
contactobjectyes
notesstring | null
is_selfbooleanyesThe "own fleet" customer of your organisation.
statusstring (active, closed)yes
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | 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

FieldTypeRequiredDescription
namestringyesYour customer's business name.
external_referencestringYour own customer id; use it to find the customer again after a retry. 1–128 printable characters, case-sensitive.
is_selfbooleanCreate your organisation's own "own fleet" customer (one per mode).
contact_namestring
contact_emailstring (email)
contact_phonestring
notesstringInternal notes for your team (never shown to the customer).
Example request
{
    "name": "Acme Deliveries Ltd",
    "external_reference": "C1042",
    "contact_name": "Sam Patel",
    "contact_email": "[email protected]"
}

StatusBodyMeaning
201CustomerSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Customer)
FieldTypeAlways presentDescription
objectstringyes
idstring (cus_…)yes
namestringyes
external_referencestring | nullyesYour own id for this customer, unique per partner and mode.
contactobjectyes
notesstring | null
is_selfbooleanyesThe "own fleet" customer of your organisation.
statusstring (active, closed)yes
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | null (date-time)
Example response 201
{
    "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

ParameterInTypeRequiredDescription
idpathstring (cus_…)yesPublic id.
StatusBodyMeaning
200CustomerSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Customer)
FieldTypeAlways presentDescription
objectstringyes
idstring (cus_…)yes
namestringyes
external_referencestring | nullyesYour own id for this customer, unique per partner and mode.
contactobjectyes
notesstring | null
is_selfbooleanyesThe "own fleet" customer of your organisation.
statusstring (active, closed)yes
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | null (date-time)
Example response 200
{
    "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

ParameterInTypeRequiredDescription
idpathstring (cus_…)yesPublic id.

Request body CustomerUpdateRequest

FieldTypeRequiredDescription
namestring
external_referencestringYour own customer id. 1–128 printable characters, case-sensitive.
contact_namestring
contact_emailstring (email)
contact_phonestring
notesstringInternal notes for your team (never shown to the customer).
Example request
{
    "contact_phone": "+44 1473 000000"
}

StatusBodyMeaning
200CustomerSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Customer)
FieldTypeAlways presentDescription
objectstringyes
idstring (cus_…)yes
namestringyes
external_referencestring | nullyesYour own id for this customer, unique per partner and mode.
contactobjectyes
notesstring | null
is_selfbooleanyesThe "own fleet" customer of your organisation.
statusstring (active, closed)yes
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | null (date-time)

Fleets

GET /partner-api/v1/fleets

List fleets

Key: management key · Scope: fleets.read

ParameterInTypeRequiredDescription
customer_idquerystring (cus_…)Only fleets of this customer.
external_referencequerystringExact match on your own reference.
statusquerystring (pending, provisioning, ready, provisioning_failed, closed)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Fleet)
FieldTypeAlways presentDescription
objectstringyes
idstring (flt_…)yes
customerstring (cus_…)yes
namestringyes
external_referencestring | null
plan_codestringyesThe plan of every service in this fleet.
statusstring (pending, provisioning, ready, provisioning_failed, closed)yesActivations wait until the fleet is ready.
timezonestringIANA time zone, e.g. Europe/London.
hosted_access_enabledboolean
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | 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

FieldTypeRequiredDescription
customer_idstring (cus_…)yesThe customer this fleet belongs to (alias: customer).
namestringyes
plan_codestringyesA plan on your rate card (GET /me → plans).
external_referencestringYour own id for this fleet. 1–128 printable characters, case-sensitive.
timezonestringIANA time zone (default Europe/London).
Example request
{
    "customer_id": "cus_89ABCDEFGHJKLMNPQRSTUVWX",
    "name": "Acme vans",
    "plan_code": "pro",
    "external_reference": "C1042-main"
}

StatusBodyMeaning
201FleetCreatedSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (FleetCreated)
FieldTypeAlways presentDescription
objectstringyes
idstring (flt_…)yes
customerstring (cus_…)yes
namestringyes
external_referencestring | null
plan_codestringyesThe plan of every service in this fleet.
statusstring (pending, provisioning, ready, provisioning_failed, closed)yesActivations wait until the fleet is ready.
timezonestringIANA time zone, e.g. Europe/London.
hosted_access_enabledboolean
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | null (date-time)
provisioningobject | nullyesThe fleet set-up operation; the event fleet.ready follows when it completes.
Example response 201
{
    "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

ParameterInTypeRequiredDescription
idpathstring (flt_…)yesPublic id.
StatusBodyMeaning
200FleetSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Fleet)
FieldTypeAlways presentDescription
objectstringyes
idstring (flt_…)yes
customerstring (cus_…)yes
namestringyes
external_referencestring | null
plan_codestringyesThe plan of every service in this fleet.
statusstring (pending, provisioning, ready, provisioning_failed, closed)yesActivations wait until the fleet is ready.
timezonestringIANA time zone, e.g. Europe/London.
hosted_access_enabledboolean
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | 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

ParameterInTypeRequiredDescription
idpathstring (flt_…)yesPublic id.

Request body FleetUpdateRequest

FieldTypeRequiredDescription
namestring
external_referencestringYour own id for this fleet. 1–128 printable characters, case-sensitive.
timezonestringIANA time zone.
Example request
{
    "name": "Acme vans (north)"
}

StatusBodyMeaning
200FleetSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Fleet)
FieldTypeAlways presentDescription
objectstringyes
idstring (flt_…)yes
customerstring (cus_…)yes
namestringyes
external_referencestring | null
plan_codestringyesThe plan of every service in this fleet.
statusstring (pending, provisioning, ready, provisioning_failed, closed)yesActivations wait until the fleet is ready.
timezonestringIANA time zone, e.g. Europe/London.
hosted_access_enabledboolean
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
closed_atstring | 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

ParameterInTypeRequiredDescription
idpathstring (flt_…)yesPublic id.

Request body FleetInvitationRequest

FieldTypeRequiredDescription
emailstring (email)yes
namestring
Example request
{
    "email": "[email protected]",
    "name": "Acme dispatch"
}

StatusBodyMeaning
201FleetInvitationSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (FleetInvitation)
FieldTypeAlways presentDescription
objectstringyes
fleetstring (flt_…)yes
emailstringyes
namestring | null
statusstring (invited, active, blocked)yes
credentials_collectedbooleanThe invitee has opened their one-time sign-in details link.
link_expires_atstring | null (date-time)
livemodebooleanyes
created_atstring (date-time)yes
operationstring (op_…)The operation that creates the tracking login.

Devices

GET /partner-api/v1/device-claims

List device claims

Key: management key · Scope: devices.read

ParameterInTypeRequiredDescription
statusquerystring (pending, approved, rejected, auto_approved)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: DeviceClaim)
FieldTypeAlways presentDescription
objectstringyes
idstring (clm_…)yes
identifier_typestring (imei, serial)yes
identifierstringyes
modelstring | null
statusstring (pending, approved, rejected, auto_approved)yes
evidence_order_refstring | null
decision_reasonstring | nullWhy it was approved or rejected (never names another owner).
devicestring | null (dev_…)
expires_atstring | null (date-time)Pending claims lapse at this time.
livemodebooleanyes
created_atstring (date-time)yes
decided_atstring | 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

FieldTypeRequiredDescription
identifier_typestring (imei, serial)
identifierstringyes
manufacturerstringyes
modelstringyes
evidence_textstringEvidence that you own the device. Knowing the IMEI is not enough.
evidence_order_refstringA Fleetalyse order or invoice reference.
fleet_idstring (flt_…)Fleet to place the device in once approved.
sim_providerstring (fleetalyse, own, none)
sim_iccidstring
labelstringVehicle name shown in your interface.
registration_platestring
vinstring17-character VIN.
Example request
{
    "identifier": "356307042441013",
    "manufacturer": "Teltonika",
    "model": "FMC130",
    "evidence_order_ref": "FA-100231"
}

StatusBodyMeaning
201DeviceClaimSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (DeviceClaim)
FieldTypeAlways presentDescription
objectstringyes
idstring (clm_…)yes
identifier_typestring (imei, serial)yes
identifierstringyes
modelstring | null
statusstring (pending, approved, rejected, auto_approved)yes
evidence_order_refstring | null
decision_reasonstring | nullWhy it was approved or rejected (never names another owner).
devicestring | null (dev_…)
expires_atstring | null (date-time)Pending claims lapse at this time.
livemodebooleanyes
created_atstring (date-time)yes
decided_atstring | null (date-time)

GET /partner-api/v1/device-claims/{id}

Retrieve a device claim

Key: management key · Scope: devices.read

ParameterInTypeRequiredDescription
idpathstring (clm_…)yesPublic id.
StatusBodyMeaning
200DeviceClaimSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (DeviceClaim)
FieldTypeAlways presentDescription
objectstringyes
idstring (clm_…)yes
identifier_typestring (imei, serial)yes
identifierstringyes
modelstring | null
statusstring (pending, approved, rejected, auto_approved)yes
evidence_order_refstring | null
decision_reasonstring | nullWhy it was approved or rejected (never names another owner).
devicestring | null (dev_…)
expires_atstring | null (date-time)Pending claims lapse at this time.
livemodebooleanyes
created_atstring (date-time)yes
decided_atstring | 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

ParameterInTypeRequiredDescription
identifierquerystringIMEI or serial (any format; matched on the canonical form).
fleet_idquerystringA flt_ id, or "none" for devices without a fleet.
customer_idquerystring (cus_…)Devices in this customer's fleets.
service_statusquerystring (none, registered, activation_pending, active, deactivation_pending, inactive, activation_failed)Current service status.
vehiclequerystring (veh_…)The device currently fitted to this vehicle.
connectivityquerystring (online, offline, unknown)Connectivity state.
simquerystring (fleetalyse, own, none)SIM provider.
ownershipquerystring (active, pending_verification, verified, rejected, released, transferred, all)Ownership state (default active = pending_verification + verified).
qquerystringFree-text search over identifier, label and plate.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Device)
FieldTypeAlways presentDescription
objectstringyes
idstring (dev_…)yes
identifier_typestring (imei, serial)yes
identifierstringyesCanonical IMEI (15 digits) or serial number (upper case).
manufacturerstring | null
modelstring | null
sourcestring (fleetalyse_order, byod, claimed, imported, migrated)yes
ownershipobjectyes
fleetstring | null (flt_…)
customerstring | null (cus_…)
vehicleobject | null
simobjectyes
connectivityobjectyes
serviceobject | null
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (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

FieldTypeRequiredDescription
identifier_typestring (imei, serial)Default imei.
identifierstringyesIMEI (14 or 15 digits; spaces and dashes removed) or serial number.
manufacturerstringyesAs listed in Supported devices.
modelstringyesAs listed in Supported devices.
fleet_idstring (flt_…)Optional fleet to place the device in (alias: fleet).
sim_providerstring (fleetalyse, own, none)
sim_iccidstringICCID of the SIM fitted in the device.
evidence_textstringWhy the device is yours (used when it needs review).
evidence_order_refstringOrder or invoice reference proving purchase.
labelstringVehicle name shown in your interface.
registration_platestring
vinstring17-character VIN.
Example request
{
    "identifier_type": "imei",
    "identifier": "356307042441013",
    "manufacturer": "Teltonika",
    "model": "FMC130",
    "fleet_id": "flt_FGHJKLMNPQRSTUVWXYZabcde",
    "label": "Van 12",
    "registration_plate": "AB12 CDE"
}

StatusBodyMeaning
201DeviceRegisteredSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (DeviceRegistered)
FieldTypeAlways presentDescription
objectstringyes
idstring (dev_…)yes
identifier_typestring (imei, serial)yes
identifierstringyesCanonical IMEI (15 digits) or serial number (upper case).
manufacturerstring | null
modelstring | null
sourcestring (fleetalyse_order, byod, claimed, imported, migrated)yes
ownershipobjectyes
fleetstring | null (flt_…)
customerstring | null (cus_…)
vehicleobject | null
simobjectyes
connectivityobjectyes
serviceobject | null
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)
verificationobjectyes

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

ParameterInTypeRequiredDescription
idpathstring (dev_…)yesPublic id.
StatusBodyMeaning
200DeviceSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Device)
FieldTypeAlways presentDescription
objectstringyes
idstring (dev_…)yes
identifier_typestring (imei, serial)yes
identifierstringyesCanonical IMEI (15 digits) or serial number (upper case).
manufacturerstring | null
modelstring | null
sourcestring (fleetalyse_order, byod, claimed, imported, migrated)yes
ownershipobjectyes
fleetstring | null (flt_…)
customerstring | null (cus_…)
vehicleobject | null
simobjectyes
connectivityobjectyes
serviceobject | null
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (date-time)

PATCH /partner-api/v1/devices/{id}

Update a device's vehicle identity

Key: management key · Scope: devices.write · Idempotency-Key required

ParameterInTypeRequiredDescription
idpathstring (dev_…)yesPublic id.

Request body DeviceUpdateRequest

FieldTypeRequiredDescription
labelstringVehicle name shown in your interface.
registration_platestring
vinstring17-character VIN.
Example request
{
    "label": "Van 12",
    "registration_plate": "AB12 CDE"
}

StatusBodyMeaning
200DeviceSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Device)
FieldTypeAlways presentDescription
objectstringyes
idstring (dev_…)yes
identifier_typestring (imei, serial)yes
identifierstringyesCanonical IMEI (15 digits) or serial number (upper case).
manufacturerstring | null
modelstring | null
sourcestring (fleetalyse_order, byod, claimed, imported, migrated)yes
ownershipobjectyes
fleetstring | null (flt_…)
customerstring | null (cus_…)
vehicleobject | null
simobjectyes
connectivityobjectyes
serviceobject | null
livemodebooleanyes
created_atstring (date-time)yes
updated_atstring (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

FieldTypeRequiredDescription
device_idstring (dev_…)yesA verified device you own.
fleet_idstring (flt_…)The fleet to activate in (required unless template_id names one).
customer_idstring (cus_…)Optional cross-check: must be the fleet's customer.
plan_codestringOptional; must equal the fleet's plan (plans are per fleet).
activate_whenstringas_soon_as_ready (default) or at:<ISO 8601 UTC> for a scheduled start.
template_idstring (tpl_…)Saved activation template (fleet, plan, naming).
sim_suspend_on_deactivatebooleanSuspend a Fleetalyse SIM when this service is later deactivated.
external_request_idstringYour 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_referencestringYour order number (not unique; shown on statements). 1–128 printable characters, case-sensitive.
Example request
{
    "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"
}

StatusBodyMeaning
200OperationAcceptedAn identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned.
202OperationAcceptedAccepted for processing.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorThe device, fleet or plan cannot be used (spec 15.5). Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (OperationAccepted)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
billingobjectyes
createdbooleanyesFalse when an earlier identical request (Idempotency-Key or external_request_id) already created this operation.
Example response 202
{
    "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

ParameterInTypeRequiredDescription
idpathstring (flt_…)yesPublic id.

Request body FleetPlanChangeRequest

FieldTypeRequiredDescription
plan_codestringyes
expected_affected_servicesintegeryesThe number of services the portal preview showed; a different current number answers 409 CONFLICT.
external_request_idstringYour 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.
Example request
{
    "plan_code": "pro",
    "expected_affected_services": 12
}

StatusBodyMeaning
200OperationAcceptedAn identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned.
202OperationAcceptedAccepted for processing.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (OperationAccepted)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
billingobjectyes
createdbooleanyesFalse 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

ParameterInTypeRequiredDescription
device_idquerystring (dev_…)Only this device.
fleet_idquerystring (flt_…)Only this fleet.
customer_idquerystring (cus_…)Only this customer.
statusquerystring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Service)
FieldTypeAlways presentDescription
objectstringyes
idstring (svc_…)yes
device_idstring (dev_…)yes
fleet_idstring (flt_…)yes
customer_idstring | null (cus_…)
plan_codestringyes
statusstring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated)yes
desired_statestring (active, inactive)yes
billingobjectyes
activated_atstring | null (date-time)
deactivated_atstring | null (date-time)
deactivation_requested_atstring | null (date-time)
scheduled_stop_atstring | null (date-time)
suspensionobject | null
simobject
connectivityobject
pending_operationobject | null
external_order_referencestring | null
versionobjectIncrease with every accepted change; events carry the same numbers as resource.version.
created_atstring (date-time)yes
updated_atstring (date-time)

GET /partner-api/v1/services/{id}

Retrieve a service

Key: management key · Scope: devices.read

ParameterInTypeRequiredDescription
idpathstring (svc_…)yesPublic id.
StatusBodyMeaning
200ServiceSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Service)
FieldTypeAlways presentDescription
objectstringyes
idstring (svc_…)yes
device_idstring (dev_…)yes
fleet_idstring (flt_…)yes
customer_idstring | null (cus_…)
plan_codestringyes
statusstring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated)yes
desired_statestring (active, inactive)yes
billingobjectyes
activated_atstring | null (date-time)
deactivated_atstring | null (date-time)
deactivation_requested_atstring | null (date-time)
scheduled_stop_atstring | null (date-time)
suspensionobject | null
simobject
connectivityobject
pending_operationobject | null
external_order_referencestring | null
versionobjectIncrease with every accepted change; events carry the same numbers as resource.version.
created_atstring (date-time)yes
updated_atstring (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

ParameterInTypeRequiredDescription
idpathstring (svc_…)yesPublic id.

Request body DeactivationRequest

FieldTypeRequiredDescription
effectivestring (immediate, scheduled)Default immediate.
atstring (date-time)With effective = scheduled: the requested stop time (ISO 8601 UTC).
suspend_simbooleanAlso suspend the Fleetalyse SIM.
notestringRecorded in your audit trail.
external_request_idstringYour 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_referencestringYour order number (not unique; shown on statements). 1–128 printable characters, case-sensitive.
Example request
{
    "effective": "immediate",
    "external_request_id": "ORDER-1042-cancel"
}

StatusBodyMeaning
200OperationAcceptedAn identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned.
202OperationAcceptedAccepted for processing.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (OperationAccepted)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
billingobjectyes
createdbooleanyesFalse 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

ParameterInTypeRequiredDescription
idpathstring (svc_…)yesPublic id.

Request body PlanChangeRequest

FieldTypeRequiredDescription
plan_codestringyes
external_request_idstringYour 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.
Example request
{
    "plan_code": "basic"
}

StatusBodyMeaning
200OperationAcceptedAn identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned.
202OperationAcceptedAccepted for processing.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (OperationAccepted)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
billingobjectyes
createdbooleanyesFalse 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

ParameterInTypeRequiredDescription
idpathstring (svc_…)yesPublic id.

Request body ReactivationRequest

FieldTypeRequiredDescription
activate_whenstringas_soon_as_ready (default) or at:<ISO 8601 UTC> for a scheduled start.
external_request_idstringYour 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_referencestringYour order number (not unique; shown on statements). 1–128 printable characters, case-sensitive.
StatusBodyMeaning
200OperationAcceptedAn identical earlier request (same Idempotency-Key or external_request_id) already finished; that operation is returned.
202OperationAcceptedAccepted for processing.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (OperationAccepted)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
billingobjectyes
createdbooleanyesFalse 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

ParameterInTypeRequiredDescription
statusquerystring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)Filter by status.
typequerystring (activation, reactivation, deactivation, plan_change, fleet_plan_change, fleet_provisioning, fleet_move, replacement, partner_transfer, hosted_user_invite, retail_migration)Filter by type.
service_idquerystring (svc_…)Only this service.
device_idquerystring (dev_…)Only this device.
fleet_idquerystring (flt_…)Only this fleet.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Operation)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly 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

ParameterInTypeRequiredDescription
idpathstring (op_…)yesPublic id.
StatusBodyMeaning
200OperationSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Operation)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly on GET /operations/{id}.
Example response 200
{
    "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

ParameterInTypeRequiredDescription
idpathstring (op_…)yesPublic id.

Request body OperationCancelRequest

FieldTypeRequiredDescription
reasonstringRecorded in your audit trail.
StatusBodyMeaning
200OperationSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Operation)
FieldTypeAlways presentDescription
objectstringyes
operation_idstring (op_…)yes
typestring (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
statusstring (queued, scheduled, running, retrying, completed, failed, requires_attention, cancelled)yes
service_idstring | null (svc_…)
device_idstring | null (dev_…)
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
service_statusstring | null (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, terminated, null)
billing_statusstring | null (not_started, accruing, stopped, null)
effective_atstring | null (date-time)When the change took effect (charging starts or stops at this instant).
scheduled_forstring | null (date-time)
external_order_referencestring | null
external_request_idstring | null
attemptsintegeryes
errorobject | null
resultobject | nullAllowlisted outcome fields: new_service_id (fleet move), plan_code, previous_plan_code, affected_services, sim, reason.
created_atstring (date-time)yes
updated_atstring (date-time)
completed_atstring | null (date-time)
request_idstring
stepsarray of objectOnly 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

ParameterInTypeRequiredDescription
statusquerystring (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated, unpaid)unpaid = open, payment_failed, action_required or overdue.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Invoice)
FieldTypeAlways presentDescription
idstring (inv_…)yes
objectstringyes
livemodebooleanyes
kindstring (access_fee, usage, hardware)yes
statusstring (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated)yes
simulatedbooleanTest-mode invoices are simulated and never charged.
numberstring | null
currencystringyes
net_minorintegerInteger minor units (pence).
tax_minorintegerInteger minor units (pence).
total_minorintegeryesInteger minor units (pence).
amount_due_minorintegeryesInteger minor units (pence).
refunded_minorintegerInteger minor units (pence).
disputed_minorintegerInteger minor units (pence).
dispute_statusstring | null
statement_idstring | null (stm_…)
periodstring | null
payment_errorstring | null
attempt_countinteger
next_payment_attempt_atstring | null (date-time)
document_availablebooleanGET /billing/invoices/{id}/document can return a link.
payableboolean
created_atstring (date-time)yes
finalised_atstring | null (date-time)
due_atstring | null (date-time)
paid_atstring | null (date-time)
voided_atstring | null (date-time)

GET /partner-api/v1/billing/invoices/{id}

Retrieve an invoice

Key: management key · Scope: billing.read

ParameterInTypeRequiredDescription
idpathstring (inv_…)yesPublic id.
StatusBodyMeaning
200InvoiceSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Invoice)
FieldTypeAlways presentDescription
idstring (inv_…)yes
objectstringyes
livemodebooleanyes
kindstring (access_fee, usage, hardware)yes
statusstring (creating, draft, open, paid, payment_failed, action_required, overdue, void, uncollectible, simulated)yes
simulatedbooleanTest-mode invoices are simulated and never charged.
numberstring | null
currencystringyes
net_minorintegerInteger minor units (pence).
tax_minorintegerInteger minor units (pence).
total_minorintegeryesInteger minor units (pence).
amount_due_minorintegeryesInteger minor units (pence).
refunded_minorintegerInteger minor units (pence).
disputed_minorintegerInteger minor units (pence).
dispute_statusstring | null
statement_idstring | null (stm_…)
periodstring | null
payment_errorstring | null
attempt_countinteger
next_payment_attempt_atstring | null (date-time)
document_availablebooleanGET /billing/invoices/{id}/document can return a link.
payableboolean
created_atstring (date-time)yes
finalised_atstring | null (date-time)
due_atstring | null (date-time)
paid_atstring | null (date-time)
voided_atstring | 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

ParameterInTypeRequiredDescription
idpathstring (inv_…)yesPublic id.
formatquerystring (pdf, hosted)pdf (default) or the hosted payment page.
StatusBodyMeaning
200InvoiceDocumentSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (InvoiceDocument)
FieldTypeAlways presentDescription
objectstringyes
invoice_idstring (inv_…)yes
formatstring (pdf, hosted)yes
urlstring (uri)yesShort-lived link issued at request time; request a new one each time.
retrieved_atstring (date-time)yes
notestring

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

ParameterInTypeRequiredDescription
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Statement)
FieldTypeAlways presentDescription
idstring (stm_…)yes
objectstringyes
livemodebooleanyes
simulatedboolean
periodstringyes
period_labelstring
period_startstring (date-time)UK midnight of the 1st, in UTC.
period_endstring (date-time)
month_secondsinteger
statusstring (frozen, invoicing, invoiced, paid, overdue, credited, void, carried_forward, settled_zero)yes
calculation_versioninteger
currencystringyes
net_minorintegeryesInteger minor units (pence).
tax_minorintegeryesInteger minor units (pence).
total_minorintegeryesInteger minor units (pence).
vat_rate_bpinteger | null
carried_forward_minorintegerInteger minor units (pence).
adjustments_minorintegerInteger minor units (pence).
delay_credit_minorintegerInteger minor units (pence).
discrepancy_countinteger
snapshot_sha256string | null
frozen_atstring | null (date-time)
tax_point_atstring | null (date-time)
invoice_idstring | null (inv_…)
linesarray of StatementSummaryLineDetail view only.
adjustmentsarray of AdjustmentDetail 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

ParameterInTypeRequiredDescription
idpathstring (stm_…)yesPublic id.
StatusBodyMeaning
200StatementSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Statement)
FieldTypeAlways presentDescription
idstring (stm_…)yes
objectstringyes
livemodebooleanyes
simulatedboolean
periodstringyes
period_labelstring
period_startstring (date-time)UK midnight of the 1st, in UTC.
period_endstring (date-time)
month_secondsinteger
statusstring (frozen, invoicing, invoiced, paid, overdue, credited, void, carried_forward, settled_zero)yes
calculation_versioninteger
currencystringyes
net_minorintegeryesInteger minor units (pence).
tax_minorintegeryesInteger minor units (pence).
total_minorintegeryesInteger minor units (pence).
vat_rate_bpinteger | null
carried_forward_minorintegerInteger minor units (pence).
adjustments_minorintegerInteger minor units (pence).
delay_credit_minorintegerInteger minor units (pence).
discrepancy_countinteger
snapshot_sha256string | null
frozen_atstring | null (date-time)
tax_point_atstring | null (date-time)
invoice_idstring | null (inv_…)
linesarray of StatementSummaryLineDetail view only.
adjustmentsarray of AdjustmentDetail 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

ParameterInTypeRequiredDescription
idpathstring (stm_…)yesPublic id.
statusquerystring (billed, deferred)deferred = verified later and billed on a later statement.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: StatementDeviceLine)
FieldTypeAlways presentDescription
device_idstring (dev_…)yes
device_labelstring | null
service_idstring (svc_…)yes
fleet_idstring | null (flt_…)
customer_idstring | null (cus_…)
plan_codestringyes
tax_basisstring (exclusive, inclusive)
statusstring (billed, deferred)yes
deferred_reasonstring | null
resolutionstring | null
billable_secondsintegeryes
numeratorintegerΣ price_minor × seconds over the segments.
denominatorintegerSeconds in the month.
amount_minorintegeryesROUND_HALF_UP(numerator / denominator).
delay_credit_minorintegerInteger minor units (pence).
external_order_referencestring | null
segmentsarray 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

StatusBodyMeaning
200BillingSummarySuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (BillingSummary)
FieldTypeAlways presentDescription
objectstringyes
currencystringyes
month_to_dateUsageEstimateyes
creditobject | null
billing_restrictedbooleanyes
restrictedbooleanyes
unpaid_total_minorintegeryesInteger minor units (pence).
unpaid_invoicesarray of Invoiceyes
payment_methodobject | null
spend_alert_minorinteger | null
latest_statement_idstring | 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

ParameterInTypeRequiredDescription
periodquerystringYYYY-MM (default: the current UK calendar month).
includequerystring (devices)Add device lines (current month).
limitqueryintegerDevice lines per page (with include=devices).
starting_afterquerystring (dev_…)Continue device lines after this device id.
StatusBodyMeaning
200UsageSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Usage)
FieldTypeAlways presentDescription
objectstringyes
periodstringyes
estimatebooleanyesTrue until the period is closed.
statement_idstring | null (stm_…)
currencystringyes
by_customerarray of objectyes
amount_minorintegeryesInteger minor units (pence).
month_to_dateUsageEstimateCurrent period only.
devicesarray of UsageDeviceLineWith include=devices (current period).
devices_has_moreboolean

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

StatusBodyMeaning
200RateCardSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (RateCard)
FieldTypeAlways presentDescription
objectstringyes
currentRateCardVersion | nullyes
scheduledarray of RateCardVersionyesAnnounced future versions.
pending_assignmentobject | null
charging_rulestringyes

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

ParameterInTypeRequiredDescription
qquerystringSearch name and description.
skuquerystringExact SKU.
modelquerystringSupported tracker model.
in_stockquerystring (true, 1)Only items in stock.
StatusBodyMeaning
200HardwareCatalogueSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareCatalogue)
FieldTypeAlways presentDescription
objectstringyes
dataarray of HardwareProductyes
has_morebooleanyes
next_cursornull
delivery_optionsarray of DeliveryOptionyes
ship_to_addressesarray of AddressyesApproved delivery addresses (keys that see every fleet only).

GET /partner-api/v1/hardware/orders

List hardware orders

Key: management key · Scope: hardware.read

ParameterInTypeRequiredDescription
statusquerystring (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled)Filter by status.
external_order_referencequerystringYour order number.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: HardwareOrderSummary)
FieldTypeAlways presentDescription
objectstringyes
idstring (ord_…)yes
referencestring
statusstring (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled)yes
payment_statusstring (paid, on_account, awaiting_payment, processing, action_required, payment_failed, overdue, simulated, void, refunded, partially_refunded)yes
livemodebooleanyes
external_order_referencestring | null
currencystringyes
gross_minorintegeryesInteger minor units (pence).
invoice_idstring | null (inv_…)
created_atstring (date-time)yes
dispatched_atstring | null (date-time)
delivered_atstring | 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

FieldTypeRequiredDescription
quote_idstring (quo_…)yesAn open, unexpired quote.
ship_tostringAddress reference (default: the quote's address).
external_order_referencestringYour order number. 1–128 printable characters, case-sensitive.
payment_modestring (invoice_immediate, credit)invoice_immediate (default): charged to your saved payment method now; credit: on account when enabled for you.
activate_before_dispatchobject | nullOnly when enabled for your account.
Example request
{
    "quote_id": "quo_rstuvwxyz123456789ABCDEF",
    "external_order_reference": "PO-7781"
}

StatusBodyMeaning
201HardwareOrderSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
410ErrorThe resource has expired. Codes: QUOTE_EXPIRED.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareOrder)
FieldTypeAlways presentDescription
objectstringyes
idstring (ord_…)yes
referencestring
statusstring (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled)yes
livemodebooleanyes
quote_idstring (quo_…)yes
external_order_referencestring | null
currencystringyes
totalsobjectyes
paymentobjectyes
linesarray of objectyes
devicesarray of objectAllocated units; each serialised unit is also a device in GET /devices.
shipmentsarray of object
ship_toAddress | null
address_lockedboolean
activate_before_dispatchobject
timelinearray of object
created_atstring (date-time)yes
allocated_atstring | null (date-time)
configured_atstring | null (date-time)
dispatched_atstring | null (date-time)
delivered_atstring | null (date-time)
cancelled_atstring | null (date-time)
cancel_reasonstring | null
tracking_chargesstringBuying 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

ParameterInTypeRequiredDescription
idpathstring (ord_…)yesPublic id.
StatusBodyMeaning
200HardwareOrderSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareOrder)
FieldTypeAlways presentDescription
objectstringyes
idstring (ord_…)yes
referencestring
statusstring (awaiting_payment, paid, allocated, configured, dispatched, delivered, cancelled)yes
livemodebooleanyes
quote_idstring (quo_…)yes
external_order_referencestring | null
currencystringyes
totalsobjectyes
paymentobjectyes
linesarray of objectyes
devicesarray of objectAllocated units; each serialised unit is also a device in GET /devices.
shipmentsarray of object
ship_toAddress | null
address_lockedboolean
activate_before_dispatchobject
timelinearray of object
created_atstring (date-time)yes
allocated_atstring | null (date-time)
configured_atstring | null (date-time)
dispatched_atstring | null (date-time)
delivered_atstring | null (date-time)
cancelled_atstring | null (date-time)
cancel_reasonstring | null
tracking_chargesstringBuying 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

FieldTypeRequiredDescription
linesarray of objectyes
delivery_optionstringA delivery option code from the catalogue.
ship_tostringAn address reference from the catalogue (default: the first approved address).
external_referencestringYour own reference for this quote. 1–128 printable characters, case-sensitive.
Example request
{
    "lines": [
        {
            "sku": "FMC130",
            "quantity": 10
        }
    ],
    "delivery_option": "uk_standard"
}

StatusBodyMeaning
201HardwareQuoteSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
402ErrorThe 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.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareQuote)
FieldTypeAlways presentDescription
objectstringyes
idstring (quo_…)yes
statusstring (open, accepted, expired, cancelled)yes
livemodebooleanyes
currencystringyes
linesarray of objectyes
deliveryobject
ship_toAddress | null
totalsobjectyes
has_backorderboolean
external_referencestring | null
expires_atstring (date-time)yesAfter this time ordering answers 410 QUOTE_EXPIRED.
accepted_atstring | null (date-time)
order_idstring | null (ord_…)
created_atstring (date-time)
tracking_chargesstringBuying hardware never starts a tracking charge.

GET /partner-api/v1/hardware/quotes/{id}

Retrieve a quote

Key: management key · Scope: hardware.read

ParameterInTypeRequiredDescription
idpathstring (quo_…)yesPublic id.
StatusBodyMeaning
200HardwareQuoteSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareQuote)
FieldTypeAlways presentDescription
objectstringyes
idstring (quo_…)yes
statusstring (open, accepted, expired, cancelled)yes
livemodebooleanyes
currencystringyes
linesarray of objectyes
deliveryobject
ship_toAddress | null
totalsobjectyes
has_backorderboolean
external_referencestring | null
expires_atstring (date-time)yesAfter this time ordering answers 410 QUOTE_EXPIRED.
accepted_atstring | null (date-time)
order_idstring | null (ord_…)
created_atstring (date-time)
tracking_chargesstringBuying 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

FieldTypeRequiredDescription
device_idstring (dev_…)yesA device supplied by Fleetalyse.
reasonstring (fault, doa, damaged_in_transit, missing, unwanted, other)yes
symptomsstringWhat is wrong (required for faults).
preferred_resolutionstring (replacement, refund, repair)
service_transferstring (transfer, none)transfer (default): move the tracking service to the replacement.
external_referencestringYour own reference. 1–128 printable characters, case-sensitive.
Example request
{
    "device_id": "dev_jkmnopqrstuvwxyz12345678",
    "reason": "fault",
    "symptoms": "No GPS fix since installation.",
    "preferred_resolution": "replacement"
}

StatusBodyMeaning
201HardwareReturnSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareReturn)
FieldTypeAlways presentDescription
objectstringyes
idstring (rma_…)yes
statusstring (requested, approved, rejected, received, replaced, refunded, closed)yes
livemodebooleanyes
reasonstringyes
symptomsstring | null
preferred_resolutionstring | null
resolutionstring | null
decision_notestring | null
service_transferstring (transfer, none)yes
external_referencestring | null
device_idstring | null (dev_…)
device_identifierstring | null
order_idstring | null (ord_…)
order_referencestring | null
replacementobject | null
service_transfer_requestedboolean
refund_net_minorintegerInteger minor units (pence).
created_atstring (date-time)yes
decided_atstring | null (date-time)
received_atstring | null (date-time)
refunded_atstring | null (date-time)
closed_atstring | null (date-time)
notestring

GET /partner-api/v1/returns/{id}

Retrieve a return

Key: management key · Scope: hardware.read

ParameterInTypeRequiredDescription
idpathstring (rma_…)yesPublic id.
StatusBodyMeaning
200HardwareReturnSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (HardwareReturn)
FieldTypeAlways presentDescription
objectstringyes
idstring (rma_…)yes
statusstring (requested, approved, rejected, received, replaced, refunded, closed)yes
livemodebooleanyes
reasonstringyes
symptomsstring | null
preferred_resolutionstring | null
resolutionstring | null
decision_notestring | null
service_transferstring (transfer, none)yes
external_referencestring | null
device_idstring | null (dev_…)
device_identifierstring | null
order_idstring | null (ord_…)
order_referencestring | null
replacementobject | null
service_transfer_requestedboolean
refund_net_minorintegerInteger minor units (pence).
created_atstring (date-time)yes
decided_atstring | null (date-time)
received_atstring | null (date-time)
refunded_atstring | null (date-time)
closed_atstring | null (date-time)
notestring

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

ParameterInTypeRequiredDescription
statusquerystring (all, active, revoked, expired)Filter by status.
classquerystring (management, tracking)Filter by key class.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Credential)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (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

FieldTypeRequiredDescription
namestringyesA name you recognise, e.g. the system that uses it.
scopesarray 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_modestring (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_idsarray of string (flt_…)With fleet_scope_mode selected.
expires_atstring | null (date-time)Optional; never later than the creating key's expiry.
ip_allowlistarray of string | nullAddresses or CIDR ranges; inside the creator's allowlist.
classstring (management, tracking)yes
Example request
{
    "name": "Warehouse app",
    "class": "management",
    "scopes": [
        "devices.read",
        "devices.write"
    ],
    "fleet_scope_mode": "all_current"
}

StatusBodyMeaning
201CredentialWithSecretSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialWithSecret)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (date-time)yes
secretstring | nullyesShown once. An idempotent replay returns null.
Example response 201
{
    "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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.
StatusBodyMeaning
200CredentialSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Credential)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.

Request body CredentialRevokeRequest

FieldTypeRequiredDescription
reasonstringRecorded in your audit trail.
StatusBodyMeaning
200CredentialRevokeResponseSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialRevokeResponse)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (date-time)yes
cascadeobjectyes

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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.

Request body CredentialRotateRequest

FieldTypeRequiredDescription
namestringDefaults to the old key's name.
scopesarray of stringSame or fewer than the old key.
fleet_idsarray of string (flt_…)A subset of the old key's fleets.
expires_atstring | null (date-time)No later than the old key's expiry.
ip_allowlistarray of string | null
overlap_secondsintegerHow long the old secret keeps working. 0 revokes it at once. Defaults to 0 with created_resources "revoke" (any other value is refused).
created_resourcesstring (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".
Example request
{
    "overlap_seconds": 3600
}

StatusBodyMeaning
201CredentialRotateResponseSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialRotateResponse)
FieldTypeAlways presentDescription
previous_keyobjectyes
created_resourcesobjectyes

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

ParameterInTypeRequiredDescription
statusquerystring (all, active, revoked, expired)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Credential)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (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

FieldTypeRequiredDescription
namestringyesA name you recognise, e.g. the system that uses it.
scopesarray 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_modestring (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_idsarray of string (flt_…)With fleet_scope_mode selected.
expires_atstring | null (date-time)Optional; never later than the creating key's expiry.
ip_allowlistarray of string | nullAddresses or CIDR ranges; inside the creator's allowlist.
Example request
{
    "name": "Acme portal feed",
    "fleet_ids": [
        "flt_2Nw8Pq4Rs6Tu8Vx1Yz3Ab5Cd"
    ],
    "expires_at": "2027-10-01T00:00:00Z",
    "ip_allowlist": [
        "203.0.113.10"
    ]
}

StatusBodyMeaning
201CredentialWithSecretSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialWithSecret)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (date-time)yes
secretstring | nullyesShown once. An idempotent replay returns null.
Example response 201
{
    "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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.
StatusBodyMeaning
200CredentialSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Credential)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.

Request body CredentialRevokeRequest

FieldTypeRequiredDescription
reasonstringRecorded in your audit trail.
StatusBodyMeaning
200CredentialRevokeResponseSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialRevokeResponse)
FieldTypeAlways presentDescription
objectstringyes
idstring (key_…)yes
classstring (management, tracking)yes
namestringyes
livemodebooleanyes
key_prefixstringyesThe first 16 characters of the secret, safe to display.
statusstring (active, expiring, expired, revoked)yesexpiring: within the warning period of expires_at, or rotated and still inside its overlap.
scopesarray 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_scopeobjectyes
ip_allowlistarray of string | null
expires_atstring | null (date-time)
rotationobject
revoked_atstring | null (date-time)
revoked_reasonstring | null (revoked, issuer_revoked, issuer_downgraded, member_removed, rotated, incident, partner_closed, null)
created_byCreatedBy
last_used_atstring | null (date-time)Updated at most once a minute.
last_used_ipstring | null
created_atstring (date-time)yes
cascadeobjectyes

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

ParameterInTypeRequiredDescription
idpathstring (key_…)yesPublic id.

Request body CredentialRotateRequest

FieldTypeRequiredDescription
namestringDefaults to the old key's name.
scopesarray of stringSame or fewer than the old key.
fleet_idsarray of string (flt_…)A subset of the old key's fleets.
expires_atstring | null (date-time)No later than the old key's expiry.
ip_allowlistarray of string | null
overlap_secondsintegerHow long the old secret keeps working. 0 revokes it at once. Defaults to 0 with created_resources "revoke" (any other value is refused).
created_resourcesstring (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".
Example request
{
    "overlap_seconds": 3600
}

StatusBodyMeaning
201CredentialRotateResponseSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (CredentialRotateResponse)
FieldTypeAlways presentDescription
previous_keyobjectyes
created_resourcesobjectyes

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

ParameterInTypeRequiredDescription
statusquerystring (pending, active, disabled)Filter by status.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: WebhookEndpoint)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (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

FieldTypeRequiredDescription
urlstring (uri)yeshttps, port 443 or 8443, public address only; redirects are not followed.
event_typesarray 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, *) | stringyes"*" = every type the creating key may receive (fleet events only for fleet-limited endpoints).
fleet_idsarray of string (flt_…) | nullOmit for all fleets (partner-wide keys only).
descriptionstring
Example request
{
    "url": "https://example.com/webhooks/fleetalyse",
    "event_types": [
        "service.activation_completed",
        "service.deactivation_completed"
    ],
    "description": "Main CRM"
}

StatusBodyMeaning
201WebhookEndpointWithSecretSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookEndpointWithSecret)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (date-time)
secretstring | nullyesSigning secret, shown once. An idempotent replay returns null.
Example response 201
{
    "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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.
StatusBodyMeaning
200WebhookEndpointSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookEndpoint)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.

Request body WebhookEndpointUpdateRequest

FieldTypeRequiredDescription
urlstring (uri)Returns the endpoint to pending until a new test event succeeds.
descriptionstring | null
event_typesarray of string
fleet_idsarray of string (flt_…) | null
enabledbooleanfalse disables; true returns a disabled endpoint to pending.
Example request
{
    "enabled": false
}

StatusBodyMeaning
200WebhookEndpointSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookEndpoint)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.
StatusBodyMeaning
200WebhookEndpointSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookEndpoint)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.
statusquerystring (pending, delivering, succeeded, failed, abandoned)Filter by status.
event_idquerystring (evt_…)Only deliveries of this event.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: WebhookDelivery)
FieldTypeAlways presentDescription
objectstringyes
event_idstring (evt_…)yes
event_typestringyes
endpoint_idstring (we_…)yes
statusstring (pending, delivering, succeeded, failed, abandoned)yesfailed = will be retried at next_attempt_at; abandoned = no more attempts.
attemptsintegeryes
last_http_statusinteger | null
last_errorstring | null
response_excerptstring | nullFirst 500 characters of your response, with anything that looks like a secret masked.
next_attempt_atstring | null (date-time)
delivered_atstring | null (date-time)
replayboolean
created_atstring (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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.

Request body WebhookRotateSecretRequest

FieldTypeRequiredDescription
overlap_secondsintegerHow long the previous secret still signs every request (second v1 value).
StatusBodyMeaning
200WebhookEndpointWithSecretSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookEndpointWithSecret)
FieldTypeAlways presentDescription
objectstringyes
idstring (we_…)yes
urlstring (uri)yes
descriptionstring | null
livemodebooleanyes
statusstring (pending, active, disabled, deleted)yespending until the signed test event is answered with 2xx.
disabled_reasonstring | null (disabled_by_partner, failing_deliveries, creator_revoked, creator_downgraded, incident, partner_closed, deleted, null)
event_typesarray 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_scopeobjectyes
secret_prefixstring | nullFirst characters of the signing secret.
previous_secret_valid_untilstring | null (date-time)During a rotation overlap, requests carry a second v1 signature with the previous secret until this time.
healthobject
created_byCreatedBy
created_atstring (date-time)yes
updated_atstring (date-time)
secretstring | nullyesSigning 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

ParameterInTypeRequiredDescription
idpathstring (we_…)yesPublic id.
StatusBodyMeaning
200WebhookTestResultSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (WebhookTestResult)
FieldTypeAlways presentDescription
objectstringyes
succeededbooleanyes
http_statusinteger | null
errorstring | null
response_excerptstring | null
duration_msinteger
event_idstring (evt_…)yes
endpointWebhookEndpointyes

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

ParameterInTypeRequiredDescription
typequerystringOnly this event type.
created_afterquerystring (date-time)Inclusive lower bound (ISO 8601 with offset).
created_beforequerystring (date-time)Exclusive upper bound.
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Event)
FieldTypeAlways presentDescription
objectstringyes
idstring (evt_…)yesStable across retries and replays — deduplicate on it.
typestring (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_versionstringyes
created_atstring (date-time)yes
livemodebooleanyes
resourceobject | nullyes
dataobjectyesThe resource snapshot of the emitting endpoint family (ids are public ids).

GET /partner-api/v1/events/{id}

Retrieve an event

Key: management key

ParameterInTypeRequiredDescription
idpathstring (evt_…)yesPublic id.
StatusBodyMeaning
200EventSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Event)
FieldTypeAlways presentDescription
objectstringyes
idstring (evt_…)yesStable across retries and replays — deduplicate on it.
typestring (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_versionstringyes
created_atstring (date-time)yes
livemodebooleanyes
resourceobject | nullyes
dataobjectyesThe resource snapshot of the emitting endpoint family (ids are public ids).
Example response 200
{
    "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

ParameterInTypeRequiredDescription
idpathstring (evt_…)yesPublic id.

Request body EventReplayRequest

FieldTypeRequiredDescription
endpoint_idstring (we_…)Omit to replay to every active endpoint you manage that received the event.
StatusBodyMeaning
202EventReplaySuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (EventReplay)
FieldTypeAlways presentDescription
objectstringyes
event_idstring (evt_…)yes
deliveriesarray of WebhookDeliveryyes

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

ParameterInTypeRequiredDescription
upcoming_daysqueryintegerInclude maintenance starting within this many days.
StatusBodyMeaning
200NoticeListSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (NoticeList)
FieldTypeAlways presentDescription
objectstringyes
dataarray of Noticeyes
has_morebooleanyes

Tracking API

GET /tracking-api/v1/ping

Check a tracking-data key

Key: tracking-data key

StatusBodyMeaning
200PingSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Ping)
FieldTypeAlways presentDescription
objectstringyes
okbooleanyes
livemodebooleanyes
partnerstring (ptn_…)yes
credentialstring | null (key_…)
credential_classstring (management, tracking)
scopesarray of string
fleet_scopestring (all, selected)
timestring (date-time)
request_idstring

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

ParameterInTypeRequiredDescription
fleet_idquerystring (flt_…)Only this fleet.
service_statusquerystring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none, tracking)tracking = active or deactivation_pending; none = no service.
includequerystring (position)Add last_position (only for vehicles whose service is active).
limitqueryintegerPage size (1–200, default 50).
cursorquerystringnext_cursor of the previous page. Bound to the key, the endpoint and the filters.
StatusBodyMeaning
200ListEnvelopeSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (each item in data: Vehicle)
FieldTypeAlways presentDescription
objectstringyes
idstring (veh_…)yes
labelstring | null
registration_platestring | null
vinstring | null
fleet_idstring | null (flt_…)yes
device_idstring | null (dev_…)
serviceobject | null
service_statusstring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none)yes
trackingobjectyes
last_positionPositionFields | null
livemodeboolean
created_atstring (date-time)yes

GET /tracking-api/v1/vehicles/{id}

Retrieve a vehicle

Key: tracking-data key · Scope: tracking.read

ParameterInTypeRequiredDescription
idpathstring (veh_…)yesPublic id.
StatusBodyMeaning
200VehicleSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Vehicle)
FieldTypeAlways presentDescription
objectstringyes
idstring (veh_…)yes
labelstring | null
registration_platestring | null
vinstring | null
fleet_idstring | null (flt_…)yes
device_idstring | null (dev_…)
serviceobject | null
service_statusstring (registered, activation_pending, active, deactivation_pending, inactive, activation_failed, none)yes
trackingobjectyes
last_positionPositionFields | null
livemodeboolean
created_atstring (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

ParameterInTypeRequiredDescription
idpathstring (veh_…)yesPublic id.
fromquerystring (date-time)yesStart (ISO 8601 with offset).
tillquerystring (date-time)yesEnd; at most 31 days after from.
include_stopsquerybooleanAlso return stops between journeys.
StatusBodyMeaning
200JourneyListSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (JourneyList)
FieldTypeAlways presentDescription
objectstringyes
vehicle_idstring (veh_…)yes
fromstring (date-time)yes
tillstring (date-time)yes
windowsarray of objectyesEntitled periods served (active service × plan history × device fitted).
clippedbooleanyes
history_daysinteger | null
dataarray of Journeyyes
has_moreboolean
simulatedboolean

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

ParameterInTypeRequiredDescription
idpathstring (veh_…)yesPublic id.
StatusBodyMeaning
200PositionSuccess.
400ErrorThe 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.
401ErrorMissing, unknown, expired, rotated-out or revoked API key, or an address outside its IP allowlist. Codes: UNAUTHENTICATED.
403ErrorThe 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.
404ErrorUnknown id — also for another partner's id, the other mode's id or an id outside the key's fleets. Codes: RESOURCE_NOT_FOUND.
409ErrorIdempotency conflict, work already in progress, or the resource is in a conflicting state. Codes: IDEMPOTENCY_CONFLICT, OPERATION_IN_PROGRESS, CONFLICT, SERVICE_INACTIVE.
422ErrorWell-formed but invalid values (details.field), or a device/plan that cannot be used. Codes: INVALID_REQUEST, DEVICE_NOT_ELIGIBLE, PLAN_NOT_AVAILABLE.
429ErrorToo many requests for this key and request class (or too many replays/test events). Codes: RATE_LIMITED.
500ErrorUnexpected error; nothing secret is exposed. Retry with backoff and the same Idempotency-Key. Codes: INTERNAL_ERROR.
503ErrorTemporarily unavailable (maintenance, the tracking platform is busy or not answering). Codes: SERVICE_TEMPORARILY_UNAVAILABLE.
Response fields (Position)
FieldTypeAlways presentDescription
objectstringyes
vehicle_idstring (veh_…)yes
device_idstring | null (dev_…)
recorded_atstring | null (date-time)yesWhen the device recorded the position (UTC).
latitudenumber | nullyesWGS84 decimal degrees.
longitudenumber | nullyesWGS84 decimal degrees.
speed_kmhinteger | nullkm/h
heading_deginteger | nullDegrees clockwise from north.
movementstring (driving, standing, no_gps, no_data, unknown)yes
age_secondsinteger | null
stalebooleanyesOlder than 10 minutes (or no data).
retrieved_atstring (date-time)yes
max_cache_age_secondsinteger
simulatedbooleanyesTrue in test mode.
Example response 200
{
    "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

HeaderTypeAlwaysMeaning
Fleetalyse-Signaturestringyest=<unix seconds>,v1=<hex HMAC-SHA256>[,v1=<previous secret>]
Fleetalyse-Event-Idstring (evt_…)yesThe event id (same as the body id); stable across retries and replays.
Fleetalyse-Event-TypestringyesThe event type.
Fleetalyse-Delivery-AttemptintegeryesAttempt number of this delivery, from 1.
Fleetalyse-Modestring (live, test)yeslive or test (endpoints only receive events of their own mode).
Fleetalyse-Replaystring (true)Present on manual replays.

Body WebhookEventPayload

FieldTypeRequiredDescription
idstring (evt_…)yesStable across retries and replays — deduplicate on it.
typestring (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_versionstringyes
created_atstring (date-time)yes
livemodebooleanyes
resourceobject | nullyes
dataobjectyes
Example body
{
    "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 answerWhat happens
2XXReceived. Answer quickly and process the event afterwards.
defaultAny other status, a redirect or no answer within 10 s: the delivery is retried.
WhatsApp us