Skip to content

Omerlo API

Andrew Ungureanu edited this page Oct 20, 2026 · 1 revision

PULSE reads its first source, Omerlo, through Omerlo's private backoffice API. This page explains how the team gets access, how the API works, and what that means for the connector.

Change from the 2026-10-14 sync. The ADRs and the first connector work assumed Omerlo's Reader API with OAuth 2 client credentials and an x-omerlo-media-id header. Omerlo has since given us access to the backoffice API, authenticated with an API key that we create ourselves (D8). Whether we also get Reader API access is an open question below.

Getting access

Step Who Status
1. Create an account on staging: staging.omerlo.app Each team member
2. Post the email you signed up with in the Omerlo Discord thread Each team member
3. Invite us to the staging tenant Alex or nitnekb (Omerlo)
4. Give us admin access to the CMS Omerlo
5. In the CMS, create an account of type integration One team member (admin)
6. Generate an API key from the integration account Same person
7. Store the key in the team's private credentials repository and share access there only Same person

Nobody sends us credentials. The API key is created by the team once we are admins on staging.

Rules for the key (Security):

  • It goes in your local .env and the private credentials repository only. It never goes in this repo, Discord, screenshots, CI logs or application logs.
  • One key per environment. Production keys are separate from staging and live in Fly.io secrets.
  • If a key leaks, revoke it in the CMS and generate a new one before doing anything else.

How the API works

Base URL

Environment Base URL
Canada (production) https://ca.omerlo.app/api
Europe (production) https://eu.omerlo.app/api
Staging To confirm with Omerlo; probably https://staging.omerlo.app/api

Authentication

Every request sends the API key in the x-api-key header:

GET /community/v2/workspaces/{workspace_id}/organizations HTTP/1.1
Host: ca.omerlo.app
x-api-key: <API key from .env>

The documentation also defines an api_key query parameter. We do not use it, because URLs end up in logs and browser history.

Workspaces

Community data is scoped by workspace: list endpoints take a workspace_id in the path. GET /composer/v2/workspaces lists the workspaces the key can see; each has an id, name, canonical_domain and locales.

How Omerlo workspaces map to PULSE tenants is to confirm (Tenancy). The likely mapping is one Omerlo client to one PULSE tenant, with one or more workspaces.

Endpoints PULSE needs

PULSE only reads. The API also creates, updates and deletes records, and the connector never calls those endpoints.

Resource List Detail Extra
Workspaces GET /composer/v2/workspaces GET /composer/v2/workspaces/{id}
Organizations GET /community/v2/workspaces/{workspace_id}/organizations GET /community/v2/organizations/{id} GET /community/v2/organizations/{organization_id}/metadata
People GET /community/v2/workspaces/{workspace_id}/people Person by id Person metadata
Events List events (by workspace) Event by id, with sessions Event metadata
Projects List projects (by workspace) Project by id Project metadata
Categories Paginated categories Category by id

Paths not written out above follow the same pattern; see the documentation for each one.

List vs detail: what each returns

List endpoints return a summary only. An organization in a list has its id, name, profile (profile_type_id, status_id, canonical_url), profile_image_key, inserted_at and updated_at.

The detail endpoint returns everything else, including the fields entity resolution needs:

Field Shape Used for
contact[] One entry per locale: email, phone, website, linkedin, facebook, instagram, twitter, bluesky Identifier matching (#26, #61)
address[] One entry per locale: street, city, country, location Matching, display
description[] Per locale, a list of blocks (text, image, slideshow, video) Display, relationships
profile.profile_categories[] Category ids Classification
profile.workspace_id The workspace the record belongs to Tenant scoping
locales[] Per-locale summary Display

Metadata (key and value pairs, such as an external CRM id) comes from a separate /metadata endpoint.

So syncing one organization takes up to three calls: the list (shared across records), its detail, and its metadata.

Pagination

Responses have data and a meta object with base, next and previous. next is null on the last page. The workspaces endpoint takes after, before and limit query parameters, so next is probably a cursor to send as after.

Neither the parameters on the community list endpoints nor the exact meaning of next is documented. Both are to confirm on staging.

Changes since the last sync

List endpoints can be sorted by updated_at (sort_by=updated_at-desc), but there is no "updated since" filter.

An incremental sync therefore reads the list newest first and stops at the first record older than the last sync's watermark (D6, #55). Deleted records never appear in a list, so only the periodic full sync can detect them.

Errors

Every error body is { "error": "<message>" }.

Status Meaning Connector behaviour
400 Invalid UUID Bug on our side: log and fail the run
401 API key missing or invalid Stop the run; the key must be checked. Never retry in a loop
403 Key lacks the role for this resource Stop the run; ask Omerlo for the permission
404 Record not found (for example deleted between list and detail) Skip the record and log it

Rate limits for the backoffice API are not documented. The "no rate limits" answer from 2026-10-14 was about the Reader API, so ask again.

Open questions for Omerlo

  • Is the backoffice API the one PULSE should use, or will we also get Reader API access (OAuth client credentials)?
  • What is the staging API base URL?
  • How do pagination parameters work on the community list endpoints (after, limit, maximum page size)?
  • Is there an "updated since" filter, or a planned webhook (the Webhooks section of the docs covers event participants only)?
  • Are there rate limits?
  • Which workspaces belong to which client, and should PULSE treat each client as one tenant?
  • Can the integration account be read-only? PULSE never writes to Omerlo, so the key should not be able to.

Clone this wiki locally