OmniPM

Authentication

Bearer tokens, scoped per workspace, revocable, rate-limited per key.

Every request carries a bearer token:

GET /api/agent/site/units
Authorization: Bearer <your key>

A missing or malformed Authorization header is a 401, as is a key that does not resolve.

Keys belong to a workspace

A key is issued for one workspace and resolves to it. Every query the request makes is scoped to that workspace before it runs — not filtered afterwards. There is no combination of key and parameter that returns another workspace's data.

Keys are stored hashed, never in plaintext, and compared in constant time. That means:

  • You cannot recover a key after issue. If it is lost, revoke it and issue a new one.
  • A key can be revoked immediately, without affecting any other key.

Scopes

A key carries an explicit list of scopes, and a request is rejected with 403 if the route's required scope is not among them.

ScopeGrants
properties:readBuildings, units, availability.
content:readBlog posts, campaigns, positions, services, site configuration.
residents:readResident records.
showings:readScheduled viewings.
inquiries:writeSubmit an enquiry.
leads:writeSubmit a lead, including a résumé upload.
analytics:writeSend page-view and event telemetry.
chat:invokeInvoke the site assistant. Cost-bearing.
check-in-links:writeCreate a guest check-in link.
reservation-links:writeCreate a reservation link.
purchases:writeAccept a supplier order.
ota:ingestRelay in OTA guest messages.

Scope your keys narrowly, and issue several rather than one. A public website is normally provisioned as three separate keys — read, actions and telemetry — so that a burst of one traffic class cannot exhaust the budget of another, and so a key embedded in a page cannot read residents.

A key that can read listings cannot read residents. That is the point of the split, and it is worth preserving when you provision.

Rate limits

Requests are counted per key, not per IP, with a default budget of 300 per hour. A key can be given its own budget where a first-party sync tool legitimately bursts.

Exceeding the budget returns 429. Back off and retry; the window is rolling.

Because limits are per key, one integration cannot exhaust another's allowance — another reason to issue separate keys rather than sharing one.

What the API is for

This is a deliberately small, mostly read-oriented surface: enough to drive a public website, feed an external assistant, and accept orders from a supplier. It is not a general-purpose interface onto the whole product, and it is not how you would build a second dashboard.

There is no OpenAPI document yet, so these pages are written by hand and can drift from the implementation. Treat a live response as authoritative over a sample here, and report anything that disagrees.

See also Errors.

On this page