OpenHouse API

Push your profiles, orders and events into OpenHouse, and trigger transactional email from your own systems — order confirmations, password resets, booking receipts.

Base URL

https://openhouse-api.6drei2.com

All endpoints speak JSON over HTTPS. Requests carry Content-Type: application/json and an Authorization: Bearer token (see Authentication). Every call operates on your own organization's data — the token decides the tenant, and there is no cross-tenant access of any kind.

Quick start

1 — get an API key. An administrator creates one under Settings → API keys in the OpenHouse app. The secret (starting oh_) is shown once — store it safely. Details: Authentication.

2 — upsert a contact
curl -s https://openhouse-api.6drei2.com/ingest/contacts \
  -H "Authorization: Bearer $API_KEY" -H 'Content-Type: application/json' \
  -d '{"records": [{"externalId": "cus_42", "email": "ada@example.com", "firstName": "Ada"}]}'
# → { "received": 1, "processed": 1, "deduplicated": 0, "skipped": [] }
3 — send a transactional email
curl -s https://openhouse-api.6drei2.com/transactional/send \
  -H "Authorization: Bearer $API_KEY" -H 'Content-Type: application/json' \
  -d '{
    "to": { "externalId": "cus_42" },
    "templateKey": "order-confirmation",
    "variables": { "orderNumber": "ORD-1042" },
    "idempotencyKey": "order-1042-confirmation"
  }'
# → { "id": "...", "status": "sent", ... }

Conventions

Batching. The ingest endpoints take { "records": [...] } with up to 1000 records per request, and answer per record:

{ "received": 3, "processed": 2, "deduplicated": 1,
  "skipped": [{ "index": 2, "reason": "..." }] }

An invalid record is skipped with a reason at its index and the valid rest still lands — retry semantics are per record, never per batch. Transactional send is the exception: one message per request, because a transactional email is triggered by one event, not a batch job.

Idempotency. Writes are safe to retry when you supply stable ids: contacts dedupe on your externalId (or email), orders and events require an externalId (your system's order/event id), and transactional sends take an optional idempotencyKey. Replaying a request counts as deduplicated and never double-writes or double-sends. The retry safety is only as good as your ids — use your system's stable identifiers, not a random value per attempt.

Strict schemas. Unknown fields are rejected, not ignored — a typo in a field name is an error you see immediately instead of data silently dropped. Emails are lowercased and validated on the way in. Timestamps are ISO 8601 strings.

Errors. Errors are JSON with a human-readable message; validation failures also carry issues, one line per problem:

{ "message": "Invalid request body",
  "issues": ["records.0.consentStatus: Invalid enum value ..."] }
  • 400 — the request shape or content is invalid; the message names what and why.
  • 401 — missing or expired token: sign in again.
  • 403 — the token's user lacks the required role.
  • 404 — the addressed resource does not exist in your organization.

A dynamic CRM. Your audiences, campaigns and reports keep up.

Customer data, analysis and campaigns usually live with three vendors, and an agent cannot run an account whose pieces do. In OpenHouse they are one product, so a question becomes a segment becomes a campaign, in one conversation.

Customer data platform

Events from the shop, the app and payments land in one profile per customer. Attributes and segments are derived from them.

CRM with a design studio

Campaigns and automations run on those segments. Emails are designed in the same place, on the brand.

Self-service BI

Anyone on the team asks a question of the customer base and gets the chart. Dashboards are described, not built.

Let’s talk.

Access is by invitation. If your team already runs a workspace, an administrator there can invite you. Otherwise, request a demo and we will set one up with you.