REST API basics

Authentication, pagination, rate limiting, and error handling - the mechanics shared by every AssetLab API endpoint.

The AssetLab REST API exposes your organization's data for integrations, BI, and automation. Every endpoint shares the mechanics on this page; per-endpoint schemas live in the interactive API reference.

Base URL and versioning

The API is served under a versioned base path (.../v1). The exact base URL for your organization is shown in Settings → API Keys. Breaking changes get a new version; v1 stays stable.

Keeping processing in Canada

Your data is stored in Canada (AWS ca-central-1, Montreal). The API itself runs in the region closest to whoever calls it, so a request from a server in the United States is processed in the United States. To keep processing in Canada, send this header on every request:

x-region: ca-central-1

If your tool cannot set headers, add forceFunctionRegion=ca-central-1 to the query string instead. The AssetLab MCP server sends the header for you from version 2.14.0.

Authentication

Every request carries an API key as a Bearer token:

curl -H "Authorization: Bearer al_live_xxxxx" \
  "https://<api-base>/v1/assets"

The key determines the organization (permanently bound) and the scopes (list). There is no other tenancy mechanism - no header, no parameter.

Requests and responses

Pagination

List endpoints paginate with page and per_page:

ParameterDefaultMax
page1-
per_page251000

Every list response carries a pagination object:

{
  "data": [ ... ],
  "pagination": { "page": 1, "per_page": 25, "total": 142, "total_pages": 6 }
}

Iterate until page == total_pages. For large syncs, prefer big per_page values over many small pages - friendlier to your rate limit.

Rate limiting

Each key has a per-minute limit (default 60 req/min), reported on every response:

HeaderMeaning
X-RateLimit-LimitRequests allowed per window
X-RateLimit-RemainingLeft in the current window
X-RateLimit-ResetUnix time the window resets

On 429, back off until the reset time. Well-behaved clients watch Remaining and pace proactively.

Errors

Errors return a JSON body with an error string and a conventional status:

StatusMeaning
400Bad request - malformed UUID, invalid payload
401Missing or invalid API key
403Key inactive, expired, missing the required scope, or the resource is not included in your plan
404Resource not found (in your organization - IDs from elsewhere 404)
409Conflict - a record already holds that unique value
429Rate limit exceeded
500Server error - safe to retry with backoff
503Your plan could not be confirmed - safe to retry with backoff

Handle 403 specially in integrations: it usually means a scope gap, which is a configuration fix, not a retry.

A 403 can also mean the resource belongs to a feature your plan does not include - Level of Service, Infrastructure and Projects are each tied to a plan - and the message names which one. Every request checks the plan, so a key stops working if your organization's plan no longer includes API access, and changes take effect within a minute.

Handle 409 specially too, and never retry it. The record already exists, and the message names the field and value that clashed - so the fix is to fetch the existing record and update it, or to skip the row. Re-sending a batch you have already loaded is the common way to meet one.

Writing data well

  1. Look up before you link. Creating an asset means first fetching real site/building/system IDs from their list endpoints.
  2. Don't send tenant identifiers. They're ignored; the key decides.
  3. Use bulk endpoints for migrations - hundreds of records per call instead of hundreds of calls.
  4. Idempotency by design - on retryable failures, re-query before re-creating to avoid duplicates.