Skip to main content

API tokens and webhooks

Connect your workspace to outside systems in two directions: mint a scoped Bearer token so a client can read from the REST API, and subscribe a URL so OnTrackio pushes events to it. Both are admin-only and both leave an audit trail.

The two surfaces are independent. A token authenticates inbound API calls; a webhook subscription is an outbound delivery target. You can use either on its own.

:::note Before you begin

  • An admin account on your workspace — the admin, it-admin, or super-admin role reaches Admin → API tokens and Admin → Settings.
  • Your workspace slug. The REST API lives at https://<slug>.app.ontrackio.com/api/; replace <slug> with yours.
  • For a webhook, a public HTTPS endpoint that can receive a POST. Private, loopback, and cloud-metadata addresses are rejected — see Webhook delivery.
  • The canonical, always-current API contract is the OpenAPI spec rendered at https://<slug>.app.ontrackio.com/api/docs. Treat this page as a guide to managing credentials and subscriptions, and the spec as the source of truth for endpoints and payloads. :::

Part 1 — API tokens

Tokens are Bearer credentials for the REST API at /api/. Each one carries an owner, a set of abilities (its scope), an optional expiry, and an optional IP allowlist. OnTrackio stores only the SHA-256 hash of a token — the plaintext is shown once, at creation, and can never be retrieved again.

Mint a token

  1. Open Admin → API tokens.

  2. Under Mint new token, fill in the fields below.

    FieldRequiredDefaultNotes
    Token nameYesFree text, max 120 characters. For your own reference, for example CI integration or Datadog metrics.
    OwnerYesThe current adminThe token inherits the owner's role. The owner must be an active user. Deactivating the owner revokes the token automatically.
    Abilities (scope)YesNoneTick at least one. Each ability grants one slice of the API — see Abilities. Use Select all read+write to tick every scope except *.
    Expires atNo6 months outA date between tomorrow and one year out. Leave blank for a non-expiring token.
    IP allowlist (CIDR)NoNoneComma- or newline-separated CIDR ranges. When set, requests from any other IP get a generic 401. See Restrict a token to an IP range.
  3. Select Mint token.

  4. Copy the plaintext from the green banner now. It starts with itam_ and is shown only on this page load; refreshing hides it for good.

:::warning The plaintext is shown once OnTrackio keeps only the SHA-256 hash. If you lose the plaintext, you can't recover it — revoke the token and mint a new one. :::

:::tip Set an expiry Leaving a token non-expiring is flagged as an audit finding under SOC 2 and ISO 27001 A.9.4.3. Prefer a dated expiry and rotate before it lapses. The form pre-fills six months for this reason. :::

Use a token

Send the plaintext in the Authorization header on every request:

curl https://<slug>.app.ontrackio.com/api/v1/hardware \
-H "Authorization: Bearer itam_<your-token>"

The guard resolves the token, checks expiry, owner status, IP, and the required ability, then runs the request as the token's owner.

ResponseMeaning
401 Missing bearer tokenNo Authorization: Bearer … header was sent.
401 Invalid or expired tokenThe token is unknown, expired, its owner is inactive, or the request IP is outside the token's allowlist. The reasons are deliberately indistinguishable.
403 Token lacks ability: <ability>The token is valid but its scope doesn't cover this endpoint. Mint a token with the right ability.

Abilities

Abilities follow a resource:action convention. Tick exactly the scopes a client needs — a token grants nothing unless at least one ability is selected.

AbilityGrants
hardware:readRead hardware records
hardware:writeCreate, update, and delete hardware
software:readRead software licenses and assignments
software:writeCreate and update software licenses
users:readRead the user directory
users:writeCreate, update, and delete users
audit:readRead the audit log and export endpoints
webhooks:readRead webhook subscriptions and deliveries
webhooks:writeCreate, update, and delete webhook subscriptions
scimSCIM 2.0 endpoints — IdP joiner / mover / leaver push
*Unrestricted full API access — use with care

:::note scim is separate from users:* The users:read / users:write abilities power the general REST API at /api/v1/users (scripts, reporting tools). The scim ability powers the SCIM 2.0 protocol at /scim/v2/ for an identity provider. Mint a dedicated scim token so you can rotate the IdP integration without disturbing other clients. See SCIM provisioning. :::

Restrict a token to an IP range

To pin a token to your fixed-egress IPs, enter one or more CIDR ranges in IP allowlist (CIDR) when you mint it. Both IPv4 and IPv6 are accepted.

203.0.113.0/24
198.51.100.42/32
2001:db8::/32

A request from outside the list is rejected with the same generic 401 as a malformed token — an attacker who steals the token but isn't behind your egress IP gets no signal that the token is otherwise valid. Leave the field blank for no restriction.

note

An invalid CIDR is rejected at submission with an inline error, so a typo never silently locks out your client. Validate the ranges against your egress before relying on them.

Review and revoke tokens

The Active tokens table lists every token with its owner, abilities, last-used time and IP, and expiry. An expired token shows an Expired badge; a non-expiring one shows an amber Never.

To revoke a token, select Revoke in its row and confirm. Revocation is immediate — any client using that token fails authentication on its next request. Both minting and revoking are written to the audit log under the api channel.

:::note Two places, one token store A legacy token form also lives under Admin → Settings → API & webhooks. It writes to the same store, so a token minted there appears in Admin → API tokens and vice versa. The dedicated Admin → API tokens page is canonical — it adds the per-ability scope picker and the IP allowlist. Use it for new tokens. :::

Part 2 — Outbound webhooks

A webhook subscription tells OnTrackio to POST a signed JSON payload to your URL whenever a subscribed event happens. Subscriptions live in the API & webhooks tab of Settings.

Subscribe a URL

  1. Open Admin → Settings, then select the API & webhooks tab.

  2. Under Webhook subscriptions, fill in the fields below.

    FieldRequiredDefaultNotes
    Subscription nameYesFree text, max 120 characters. For your reference.
    URLYesA valid public HTTPS endpoint, max 500 characters. Receives the POST.
    EventsYesSelect at least one event, or * for all. Hold Cmd / Ctrl to select several. See Events.
  3. Select Subscribe.

A signing secret is generated automatically for the subscription and used to sign every delivery. New subscriptions are active immediately.

:::warning Your endpoint must be publicly reachable OnTrackio refuses to deliver to loopback, private (RFC 1918), link-local, or cloud-metadata addresses, and to non-HTTP(S) schemes — this stops a pasted URL being used to probe internal infrastructure. A subscription to such a URL records the rejection as a failed delivery. :::

Events

Subscribe to specific events, or to * to receive everything (including events added later).

EventFires when
hardware.createdA hardware asset is created
hardware.updatedA hardware asset is edited
hardware.assignedA hardware asset is assigned to a person
hardware.recoveredA hardware asset is recovered from a person
asset_request.createdAn employee submits an asset request
asset_request.approvedA request is approved
asset_request.rejectedA request is rejected
asset_request.fulfilledA request is fulfilled
software.assignedA software license seat is assigned
software.revokedA software license seat is revoked
user.offboardedA user is offboarded
*Any of the above, current and future

How webhook delivery works

For each active subscription that matches the event, OnTrackio sends one POST. Delivery is best-effort and never blocks the action that triggered it — a failing endpoint won't break an assignment or a request.

PropertyValue
MethodPOST
Content-Typeapplication/json
X-Itam-EventThe event name, for example hardware.assigned
X-Itam-SignatureHex-encoded HMAC-SHA256(secret, raw_body) — verify this to confirm authenticity
User-AgentOnTrackio-ITAM-Webhook/1.0
Timeout8 seconds
RetriesNone — each event is delivered once; a non-2xx or timeout is recorded as failed

Every delivery — success or failure — is logged with its response status and body. The subscription's row shows the last delivery time, a running total, and a status badge: a green 2xx badge, a red status code on failure, Paused when inactive, or No deliveries before the first attempt.

Payload shape

The body is a JSON object with the event, a timestamp, and an event-specific data object:

{
"event": "hardware.assigned",
"occurred_at": "2026-06-07T10:15:30+00:00",
"data": {
"hardware_id": 412,
"asset_tag": "OT-000412",
"user_id": 87
}
}

Verify the signature

Recompute the HMAC over the exact raw request body with your subscription's secret and compare it to X-Itam-Signature. Reject the request if they differ.

$expected = hash_hmac('sha256', $rawBody, $secret);
if (! hash_equals($expected, $request->header('X-Itam-Signature'))) {
abort(401);
}

:::tip Compare against the raw body Sign the bytes exactly as received, before any JSON parsing or re-encoding. Re-serializing the payload changes whitespace and key order, which breaks the comparison. :::

Test, pause, and delete a subscription

  • Test sends a synthetic test.ping delivery to that one endpoint so you can confirm connectivity without waiting for a real event. It targets only the selected subscription, not every subscriber. Save any URL change first.
  • A subscription with no active events stops receiving deliveries and shows a Paused badge.
  • Delete removes the subscription. Past deliveries are no longer reachable from the UI.

Troubleshooting

SymptomWhat to do
API call returns 401 Missing bearer tokenAdd the Authorization: Bearer <token> header. The value is the plaintext shown once at mint time, starting with itam_.
API call returns 401 Invalid or expired tokenThe token is unknown, expired, its owner was deactivated, or the request IP is outside the token's allowlist. Check the expiry and owner status in Admin → API tokens, and confirm the calling IP is in any CIDR allowlist.
API call returns 403 Token lacks abilityThe token's scope doesn't cover the endpoint. Mint a token that includes the required ability — for example hardware:write to create assets.
Lost the token plaintextIt's unrecoverable by design. Revoke the token and mint a new one.
Webhook never arrivesConfirm the subscription is active and subscribed to the right event (or *). Use Test to probe connectivity, then check the status badge and last-delivery total.
Webhook status badge shows a red code or No deliveriesThe endpoint returned a non-2xx, timed out (8 s), or the URL was rejected as private/loopback/metadata. Confirm the endpoint is public HTTPS and responds within the timeout. There is no automatic retry.
Signature check fails on your sideRecompute HMAC-SHA256 over the raw body with the subscription's secret, hex-encoded, and compare to X-Itam-Signature. Don't parse and re-serialize the body first.
Token appears that you didn't mint hereIt was likely created via the legacy form under Settings → API & webhooks, which shares the same store. Manage it from Admin → API tokens.