Skip to main content

Customer Data Access

This guide is for building product features on your workspace data quickly. Start with the access flow, then use the schema reference further down when you need implementation detail.

What You Get

  • One dedicated database per workspace.
  • Ready-to-query views for people and companies.
  • Safe write path for customer overrides.
  • A custom schema (tenant_custom) for your app-specific tables.

Quick Start: Get Access in Minutes

1) Check workspace database status

Use:
GET /api/v2/tenants/status

2) Provision if needed

If status is not active, run:
POST /api/v2/tenants/provision
You are ready when status returns active.

3) Reveal a connection URI

Use:
POST /api/v2/tenants/connection-uris/reveal
{
  "kind": "read",
  "pooled": true
}
Use kind: "override" when your app needs to write overrides or create custom tables.

4) Connect from your app

import { Client } from 'pg'

const client = new Client({ connectionString: process.env.DB_URI })
await client.connect()

const { rows } = await client.query(
  'SELECT identity_key, display_name FROM dl_resolved.people ORDER BY updated_at DESC LIMIT 20'
)

Build Features Fast (Vibe-Coding Patterns)

Read customer records for app screens

Use:
  • dl_resolved.people
  • dl_resolved.companies
These views already merge base records and customer overrides.

Let users correct data in your app

Write to:
  • dl_override.person_overrides
  • dl_override.company_overrides
Pattern:
INSERT INTO dl_override.person_overrides (
  identity_key,
  status,
  identity_payload_patch,
  raw_payload_patch,
  tombstoned,
  updated_at
) VALUES (
  $1, $2, $3::jsonb, $4::jsonb, false, now()
)
ON CONFLICT (identity_key) DO UPDATE
SET status = EXCLUDED.status,
    identity_payload_patch = EXCLUDED.identity_payload_patch,
    raw_payload_patch = EXCLUDED.raw_payload_patch,
    tombstoned = false,
    updated_at = now();

Store app-specific objects

Create your own tables in tenant_custom:
CREATE TABLE IF NOT EXISTS tenant_custom.account_segments (
  id text PRIMARY KEY,
  segment text NOT NULL,
  created_at timestamptz NOT NULL DEFAULT now()
);

API Endpoints You Will Use

  • GET /api/v2/tenants/status
    • Check whether your workspace database is active.
  • POST /api/v2/tenants/provision
    • Create database resources for the current workspace.
  • GET /api/v2/tenants/connection-uris/metadata
    • Return project/database/role metadata for active workspaces.
  • POST /api/v2/tenants/connection-uris/reveal
    • Reveal pooled URI for read or override.
  • POST /api/v2/tenants/connection-uris/rotate
    • Rotate password for read or override.
  • GET /api/v2/tenants/sql-schema
    • Return machine-readable contract for schemas and role access.

Deep Reference: Schema Contract

Managed schemas (platform-owned)

  • dl_cache
    • person_enrichments
    • company_enrichments
  • dl_override
    • person_overrides
    • company_overrides
  • dl_resolved
    • people (view)
    • companies (view)
  • dl_meta
    • schema_migrations
    • tenant_settings

Customer schema (you own this)

  • tenant_custom
    • Full DDL + DML allowed for override role.

Deep Reference: Role Access

  • dl_tenant_read
    • SELECT on dl_resolved.*
  • dl_tenant_override
    • SELECT on dl_resolved.*
    • SELECT/INSERT/UPDATE/DELETE on dl_override.*
    • Full DDL + DML on tenant_custom.*
  • dl_platform_runtime
    • Internal app/runtime operations across managed schemas

Operational Notes

  • Database access is workspace-scoped, not user-scoped.
  • If the backing project was deleted manually, run POST /api/v2/tenants/provision again.
  • Branch lifecycle is platform-managed for this tenant model.