relasightBack to insights

Many systems.
One customer picture.

Bring trusted warehouse, CRM, billing and support data into Relasight automatically. Keep the source behind every observation, and turn the combined evidence into decisions.

Proposed integration API · v0.2.0 draft

A first Supabase backend and shared-workspace login are now live. This page describes the broader proposed contract; its .invalid examples do not transmit data. Read the live POC connection guide for the deployed endpoints, authentication and limits.

Download OpenAPI contractDownload example batch

Connect through the pipeline you already operate

Your systemsWarehouse · CRM · Support · Billing
→
Your integration jobMap records · Send changes · Reconcile results
→
RelasightSource evidence · Customer picture · Insights

Start with an outbound push integration. A scheduled job inside your network reads an approved warehouse view, maps its columns, and sends changed records over HTTPS. Relasight does not need direct database credentials or inbound access to your warehouse. Any system that can emit the contract can contribute; vendor-specific connectors are not yet implemented.

Use a separate registered source for each independently versioned feed, for example warehouse-production, crm-production and support-production. If the warehouse already consolidates CRM data, choose one authoritative feed for those observations to avoid counting the same evidence twice.

A first successful sync

  1. An administrator provisions a workspace service token with the required permissions. Save it in your job's secret store.
  2. Register each source. Save the returned source ID in pipeline configuration.
  3. Send customer records first. Poll every batch until terminal, and reconcile each item before sending dependent observations.
  4. Send observations referencing that source's customer external ID. Link identities across systems using an approved crosswalk.
  5. Schedule incremental sync, check rejected rows, and verify the customer evidence and insight counts.
# Documentation only. This placeholder host does not resolve.
export RELASIGHT_BASE_URL="https://api.relasight.invalid/v1"
# Inject RELASIGHT_TOKEN from your secret store; never commit it.
curl --fail-with-body "$RELASIGHT_BASE_URL/sources" \
  -H "Authorization: Bearer $RELASIGHT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: register-warehouse-prod-v1" \
  --data '{"name":"Warehouse production","kind":"warehouse"}'

# Replace source_id in the file with the returned ID.
curl --fail-with-body "$RELASIGHT_BASE_URL/ingestion/batches" \
  -H "Authorization: Bearer $RELASIGHT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: warehouse-run-20260912-batch-001" \
  --data-binary @integration-batch.json

Customer and observation payload

This batch shows the two record types together. Production jobs should load customers and confirm success before their dependent observations. Items in one batch are processed in array order, but separate batches may finish out of order.

{
  "source_id": "src_warehouse",
  "items": [
    {
      "operation": "customer.upsert",
      "external_id": "C-1042",
      "source_version": 42,
      "source_updated_at": "2026-09-12T10:00:00Z",
      "customer": {
        "name": "Cedar Works",
        "type": "company",
        "email": "hello@cedar.example",
        "industry": "Professional services"
      }
    },
    {
      "operation": "observation.upsert",
      "external_id": "contract-778-renewal",
      "customer_external_id": "C-1042",
      "source_version": 7,
      "source_updated_at": "2026-09-12T10:00:00Z",
      "observation": {
        "attribute": "renewal_date",
        "value": "2026-10-10",
        "effective_at": "2026-09-12T09:00:00Z",
        "confidence": "Verified",
        "context": "Contract register, contract 778"
      }
    }
  ]
}

One identity, many independent sources

A source record is keyed by (workspace, source_id, entity kind, external_id). External IDs must be stable, case-sensitive strings, never row numbers. Warehouse customer C-1042 and support organization org-882 remain separate until explicitly linked. Matching an email address or company name never automatically merges records.

Use your warehouse master customer key to build a reviewed crosswalk. Both source customers must exist before posting a link. Linking aliases preserves every source record, version and observation; it does not delete evidence. Repeating the same link returns the existing canonical customer. Contradictory identity operations return 409 for review. A future administrative unlink workflow must support audited correction; that endpoint is outside this draft.

{
  "left": {
    "source_id": "src_warehouse",
    "external_id": "C-1042"
  },
  "right": {
    "source_id": "src_support",
    "external_id": "org-882"
  },
  "reason": "Approved warehouse-to-support identity crosswalk"
}

Keep source ownership visible

A customer upsert updates only that source's profile. It is a complete source profile: name and type are required; omitted optional fields clear that source's old optional values. A linked canonical profile uses an administrator's per-field source priority; an absent value falls back to the next source. Without configured priority, conflicting profile values require review. Cross-source arrival order never decides the winner.

Observations use stable event or fact IDs, such as contract-778-renewal. Higher source versions replace that source observation's current version while preserving its history. An observation's customer and attribute cannot be changed under the same external ID; retract it and create a new ID. Distinct events must receive distinct IDs. Retracting one source observation never retracts another source's evidence.

The proposed production resolver keeps effective time and ingestion time separate. It shows same-effective-time disagreements between sources and excludes disputed attributes from matching until resolved. Confidence is asserted by the source, not independently certified by Relasight. The current browser POC uses day-level dates; production timestamps retain UTC precision.

Warehouse mapping and incremental delivery

Your fieldAPI fieldRule
customer_keyexternal_idStable source business key, serialized as a string
customer_name / entity_typecustomer.name / typeCompany or person; no existing customer dimension required
change_sequencesource_versionMonotonically increasing positive integer per source entity
last_modified_utcsource_updated_atSource modification timestamp, UTC
renewal_dateobservation.valueYYYY-MM-DD, attribute renewal_date
fact_valid_fromobservation.effective_atWhen the fact became true, not when the sync ran

The following is vendor-neutral pseudocode; adapt parameter binding, pagination and snapshot isolation to your warehouse. Do not use this as a literal connector implementation.

SELECT customer_key, customer_name, entity_type, email,
       last_modified_utc, change_sequence
FROM approved_relasight_customer_view
WHERE (last_modified_utc > :last_time
       OR (last_modified_utc = :last_time AND customer_key > :last_key))
  AND last_modified_utc <= :run_upper_bound
ORDER BY last_modified_utc, customer_key;

For each bounded page:
  map to API records; persist payload + idempotency key in a durable outbox
  send batch; poll status; inspect every item result
  retry transient failures with the identical key and payload
  quarantine rejected records durably with their source keys and errors
  checkpoint only after all items are applied, duplicate, stale,
    or durably quarantined with an explicit repair/replay process

Use a stable run upper bound and a tie-breaker key to avoid skipping rows sharing timestamps. Prefer a change log or CDC sequence when updates can arrive late or clocks can move backwards. For polling, replay a bounded overlap window using stable versions and perform periodic full reconciliation. Full snapshots must compare source keys explicitly; absence from a partial extract is never a delete.

Handle hard deletes using a change log/tombstone feed. customer.unlink removes only that source's alias from the active picture and excludes its contributions; history stays auditable. A linked customer with other sources remains. This is not a workspace-wide privacy erasure endpoint. Route full erasure to a separate authorized administrative process before production rollout.

For an initial load, create customer batches first, resolve errors, then load observations and cross-source links. For updates, coalesce versions for each entity and preserve stable source versions across retries. If a warehouse has only timestamps, persist your own per-entity sequence in the integration layer; do not derive versions from wall-clock time without collision handling.

Proposed endpoints

Method & pathPermissionResponse
POST /v1/sourcessources:write201 source ID
GET /v1/sourcessources:read200 items, next_cursor; default 50, maximum 100
POST /v1/ingestion/batchesingestion:write202 batch ID and relative status URL
GET /v1/ingestion/batches/{batch_id}ingestion:read200 status and per-item results
POST /v1/identity-linksidentity:write200 canonical customer ID and aliases

Proposed defaults: UTF-8 JSON, at most 500 items and 1 MB uncompressed per batch, and 60 mutation requests per workspace per minute. These are design targets, not measured service limits. Source lists use an opaque cursor; follow next_cursor until null. Batches contain bounded results and do not paginate.

Operations and validation

For all operations, timestamps use RFC 3339 UTC with a Z suffix. Positive versions increase per source entity, not per batch. Future-effective observations may be stored but do not enter today's picture. Unexpected fields, incompatible operation payloads, invalid dates and oversize values reject. No incoming field sets marketing consent or contact eligibility.

Reliable retries without duplicate facts

Every mutation requires an Idempotency-Key. The service scopes it to the workspace and route and stores the request digest and response for at least seven days. A retry with the same body returns the original result; reuse with a different body returns 409. After expiry, entity identity and source_version still prevent duplicate application.

Equal entity version and identical canonical payload returns duplicate. Equal version with different content returns version_conflict. A lower version returns stale without changing data. A higher version appends history and updates the source projection. Retrying rejected content with a corrected body requires a new batch key; if its version was never applied it can retain that entity version.

A 202 means queued, not imported. Poll with backoff until completed, completed_with_errors or failed. Results include zero-based input index, external_id, status and any error code/detail. Successful items are not rolled back when another item rejects. Treat a failed batch with incomplete results as uncertain: replay with the same key and reconcile; do not assume the whole batch was rolled back.

{
  "id": "batch_123",
  "status": "completed_with_errors",
  "results": [
    {
      "index": 0,
      "external_id": "C-1042",
      "status": "applied",
      "customer_id": "cust_901"
    },
    {
      "index": 1,
      "external_id": "contract-778-renewal",
      "status": "rejected",
      "code": "unknown_customer",
      "detail": "The referenced source customer was not found."
    }
  ]
}

The result example illustrates partial success in a different batch with an unresolved reference. For transport failures or 5xx, retry the identical request with capped exponential backoff and jitter. On 429 honor Retry-After. Do not automatically retry 401/403, 409 or validation errors without correcting the cause. Store rejected rows, alert an owner, and make repair/replay visible in your pipeline dashboard.

Request-level errors use application/problem+json with type, title, status, detail and request_id. Envelope errors reject the batch before queuing; record-level errors appear in the batch result. Tokens, payload contents and personal data must not appear in operational error logs.

Access and deployment boundaries

Service tokens belong to one workspace and carry explicit permissions. Source-restricted tokens may write and read only their configured sources. Identity linking requires access to both sources and a separate privileged permission. The backend must enforce these checks on every resource, including batch polling; an inaccessible identifier returns 404. Client-supplied workspace IDs never select the authorization boundary.

Keep tokens in your server-side secret manager, rotate and revoke them, use TLS, and record actor/source/request ID in an audit log. An ingestion token should not grant customer-wide export access. Private-network warehouse jobs need outbound HTTPS only. The production service must define retention, erasure, encryption, tenant isolation and monitoring before accepting real data.

For the proposed Gold customer-managed deployment, run the same versioned contract inside the customer's network and configure a different base URL. A Silver private deployment remains a commercial option to evaluate. Neither hosting option nor a managed connector is implemented by this POC. These documentation examples do not transmit data. Signed-in workspaces store data in Supabase.

Acceptance checklist for the backend phase

Standards used

The downloadable contract uses OpenAPI 3.1.1. Request-level errors follow RFC 9457 Problem Details. Relasight endpoint names, permissions, limits and sync semantics above are proposed product decisions, not claims about an existing service.