Manifold exposes a versioned, read-only REST API at /api/v1 for reading your organisation’s core gas data (properties, appliances, checks, and certificates) into your own tools and integrations. Access is by API key, and every response is scoped to the organisation that owns the key, so no other tenant’s data is ever reachable.
- Base path: /api/v1, relative to your Manifold console domain.
- Read-focused: the core entities (properties, appliances, checks, certificates) are read-only; the one write capability is webhook subscription management (webhooks:write), used to subscribe and unsubscribe event webhooks.
- Stable shapes: each endpoint returns a curated set of fields, so office-internal columns are never exposed and the published contract stays steady as the product evolves.
- 1Open Settings then API in the console; you need the manage-organisation permission.
- 2Create a key, give it a name, and choose its scopes.
- 3Copy the key. It starts with mfd_live_ and is shown only once. Store it somewhere secret; if you lose it, revoke it and mint a new one.
- 4Revoke a key at any time from the same screen; a revoked key stops working immediately.
Send the key on every request using either header form. There is no session or cookie on this path. The key is the credential.
- Authorization: Bearer mfd_live_<your key> - recommended.
- X-API-Key: mfd_live_<your key> - alternative.
- Test a key with GET /api/v1/me; it returns the organisation and the key’s granted scopes, and is the canonical “does my key work?” call.
- A missing, malformed, revoked, or expired key returns 401; a valid key that lacks the scope an endpoint requires returns 403.
A key grants only the capabilities you select. The available scopes are:
- properties:read - list and read properties.
- appliances:read - list and read appliances.
- checks:read - list and read gas safety checks.
- certificates:read - list and read generated certificates (the CP12 / Landlord Gas Safety Record and related types).
- webhooks:write - create and delete event webhook subscriptions via POST /api/v1/webhooks and DELETE /api/v1/webhooks/{id}. This is the scope the Zapier triggers use to subscribe and unsubscribe; it is not granted by default, so add it explicitly to an integration key.
- GET /api/v1/me - connection test; returns the organisation and the key’s scopes.
- GET /api/v1/properties and /api/v1/properties/{id} - optionally filter the list by client_id or status.
- GET /api/v1/appliances and /api/v1/appliances/{id} - optionally filter the list by property_id.
- GET /api/v1/checks and /api/v1/checks/{id} - optionally filter by property_id or status (see Status and Lifecycle for the status values).
- GET /api/v1/certificates and /api/v1/certificates/{id} - optionally filter the list by property_id.
- An unknown, non-id, or other-organisation {id} returns 404. The API never reveals whether a record exists in another workspace.
List endpoints return a data array plus a pagination object; single-item endpoints return the record under data; errors return a message with an appropriate HTTP status.
- Page with ?limit= (default 50, maximum 100) and ?offset= (default 0).
- List shape: a data array alongside pagination with limit, offset, and has_more (true when more rows follow the current page).
- Item shape: the record under a single data key.
- Error shape: an error message; for example a 400 when a filter id is malformed.
- Dates and timestamps are ISO 8601 strings, and ids are UUIDs.
Alongside the REST endpoints, Manifold serves an OData 4.0 feed built for Power BI and other analytics tools that speak OData. It exposes the same four entities with the same key auth and the same tenant scoping.
- Service document at /api/v1/odata, schema at /api/v1/odata/$metadata, and collections at /api/v1/odata/{Set}.
- Entity sets: Properties, Appliances, Checks, and Certificates. Each needs the matching read scope on your key.
- In Power BI, choose the OData feed source, enter the service URL, and authenticate with your API key as the Web API key.
- Collections page with $top and $skip, and responses carry a next-page link until the set is exhausted.
- The connector is gated by the Power BI entitlement, included from the Growth plan; without it the feed returns a plan message.
Troubleshooting
- Power BI cannot connect: test the key with GET /api/v1/me first, then confirm the plan includes the connector.
- A collection is missing: the key lacks that entity’s read scope; mint a key with the scope you need.
Instead of polling, you can have Manifold push events to you. Register a webhook in Settings then API & webhooks: give it a name, an https destination URL, and the events it should fire for. When a subscribed event happens, Manifold sends a signed POST to your URL. This is also the mechanism the Zapier triggers use behind the scenes.
- certificate.generated - a Gas Safety Record (CP12/LGSR) was generated for a check.
- renewal.due - a property crossed into a due-soon or overdue compliance state (emitted by the daily renewal job on the transition).
- defect.raised - a gas defect was created, either from a check submission (origin check_item) or logged manually in the office (origin manual).
- Pause a webhook to stop deliveries without losing it; delete it to unsubscribe entirely.
- Manage webhooks programmatically with an API key that has the webhooks:write scope: POST /api/v1/webhooks with { name, destination_url, events } to subscribe (the response includes the signing secret once), and DELETE /api/v1/webhooks/{id} to unsubscribe. These are the calls the Zapier triggers make for you.
- The signing secret (it starts with whsec_) is shown once when you create the webhook and is never shown again. Store it somewhere safe.
Every delivery is an HTTP POST with a JSON body of the shape { "event": "<event name>", "data": { … } }. The data object is a curated, public-shaped record: the same discipline as the read endpoints, so office-internal fields are never included. Each delivery carries headers identifying and authenticating it.
- X-Manifold-Event - the event name, e.g. certificate.generated.
- X-Manifold-Signature - the signature, formatted as sha256=<hex>; see Verifying the Signature.
- X-Manifold-Delivery-Attempt - the 1-based attempt number for this delivery.
- Content-Type is application/json; the User-Agent is Manifold-Webhooks/1.
- certificate.generated data: id, reference, cert_type, gas_safety_check_id, property_id, client_id, engineer_name, engineer_gas_safe_no, check_date, next_due_date, overall_result, generated_at.
- renewal.due data: property_id, status (due_soon or overdue), next_due_date, address_line1, address_line2, city, postcode, tenant_name, client_id.
- defect.raised data: id, property_id, gas_safety_check_id, gas_appliance_id, description, category, priority, status, origin (check_item or manual), recommended_action.
Verify every delivery so you only act on genuine Manifold events. The X-Manifold-Signature header is sha256= followed by the HMAC-SHA256 of the EXACT raw request body, keyed by your webhook signing secret. Recompute it over the bytes you received and compare.
- 1Read the raw request body as bytes. Do not re-serialise the parsed JSON, as that can change the bytes and break the signature.
- 2Compute HMAC-SHA256 over those raw bytes using your signing secret (the whsec_ value) as the key, and hex-encode the result.
- 3Build the expected value as the string sha256= followed by that hex digest.
- 4Compare it to the X-Manifold-Signature header using a constant-time comparison; reject the delivery if they differ.
Troubleshooting
- Signature never matches: confirm you are hashing the raw body bytes, not a re-stringified object, and that you are using the secret from this exact webhook.
- Deliveries stop arriving: a webhook returning a 4xx (other than 429) is treated as a permanent rejection and not retried; 5xx and 429 responses are retried a few times with backoff. Check the last delivery status shown next to the webhook in Settings.
- No deliveries at all: make sure the webhook is Active (not paused) and that its URL is a public https endpoint. Internal, loopback, and private-range hosts are blocked.
Manifold ships a Zapier integration whose triggers map one-to-one onto these events. Authentication is your API key; each trigger is a REST hook that subscribes by creating a webhook for its event and unsubscribes by deleting it: exactly the management actions on this page.
- New Certificate Generated → certificate.generated.
- Renewal Due → renewal.due.
- Defect Raised → defect.raised.
- In Zapier, connect Manifold with your API key, pick a trigger, and Zapier registers the webhook for you; turning the Zap off removes it.
- Requests are rate-limited per key; page through results rather than hammering an endpoint, and pace bulk reads.
- Treat keys and webhook signing secrets like passwords: never commit them to source control or put them in a browser-visible field.
- Use a separate key per integration so you can revoke one without disrupting the others.
- Respond to a webhook quickly (a 2xx) and do slow work asynchronously; Manifold times out a delivery after about ten seconds and will retry.