Skip to main content

Customer Data Access

This guide is for building product features on your workspace data quickly. It covers two access paths:
  • query_customer_db, the agent-callable tool for bounded SQL reads and storage-scoped writes.
  • Direct PostgreSQL connection URIs for apps, BI tools, and admin workflows.
Start with the tool path when an agent is working inside Deepline. Use direct connection URIs when your own application needs a Postgres connection string.

What You Get

  • One dedicated database per workspace.
  • Ready-to-query views for people and companies.
  • An agent-writable storage schema for query_customer_db.
  • Direct connection roles for application and reporting access.

Agent Tool: query_customer_db

Use query_customer_db when Claude, Codex, or another agent needs to inspect workspace data through Deepline APIs.
deepline tools execute query_customer_db --payload '{
  "sql": "SELECT domain, company_name FROM enrichments.companies ORDER BY updated_at DESC LIMIT 20"
}'
query_customer_db runs one SQL statement at a time. It supports:
  • SELECT, EXPLAIN, and read-only WITH queries.
  • Aggregate queries such as SELECT count(*) ....
  • INSERT, UPDATE, DELETE, CREATE TABLE, CREATE INDEX, ALTER TABLE, DROP TABLE, and TRUNCATE only for schema-qualified storage.<table> targets.
The storage schema is the safe write path for agent-created tables and scratch state:
deepline tools execute query_customer_db --payload '{
  "sql": "CREATE TABLE IF NOT EXISTS storage.agent_notes (id text PRIMARY KEY, note text NOT NULL, created_at timestamptz NOT NULL DEFAULT now())"
}'
Then query or update that table through the same tool:
deepline tools execute query_customer_db --payload '{
  "sql": "INSERT INTO storage.agent_notes (id, note) VALUES ('\''run-123'\'', '\''ready for review'\'') ON CONFLICT (id) DO UPDATE SET note = EXCLUDED.note"
}'
deepline tools execute query_customer_db --payload '{
  "sql": "SELECT id, note, created_at FROM storage.agent_notes ORDER BY created_at DESC LIMIT 20"
}'
Do not use query_customer_db for arbitrary DDL or migrations. These examples are blocked:
CREATE TABLE agent_notes (...);
CREATE TABLE tenant_custom.agent_notes (...);
DELETE FROM enrichments.companies WHERE domain = 'example.com';
If you see Only read statements or schema-qualified storage tables are supported. or Customer DB writes are only allowed for schema-qualified storage tables., rewrite the statement to target storage.<table> exactly, or make the query read-only.

Quick Start: Get Access in Minutes

Use this flow when you need a direct PostgreSQL connection string.

1) Check workspace database status

Use:
GET /api/v2/ingestion/status

2) Provision if needed

If not provisioned, run:
POST /api/v2/ingestion/provision
You are ready when provisioned is true and plane status is active.

3) Reveal a connection URI

Use:
POST /api/v2/ingestion/connection-uris/reveal
{
  "kind": "customer_db",
  "pooled": true
}
The revealed customer DB URI uses the workspace-scoped customer database role. It can read permitted workspace schemas and can write to the storage schema. Use the same storage.<table> convention for app-created tables unless you are working through a separate admin/runtime migration path.

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.

Store app-specific objects through the agent tool

Create agent-owned tables in storage:
CREATE TABLE IF NOT EXISTS storage.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/ingestion/status
    • Check whether your workspace database is provisioned and active (API key or session auth).
  • POST /api/v2/ingestion/provision
    • Create database resources for the current workspace (dashboard/admin session).
  • GET /api/v2/ingestion/connection-uris/metadata
    • Return project/database/role metadata for active workspaces (dashboard/admin session).
  • POST /api/v2/ingestion/connection-uris/reveal
    • Reveal a pooled URI for customer_db (dashboard/admin session).
  • POST /api/v2/ingestion/connection-uris/rotate
    • Rotate the customer DB role password (dashboard/admin session).

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

Agent storage schema

  • storage
    • DDL and DML allowed for query_customer_db and the customer DB role.
    • Always schema-qualify writes as storage.<table>.

Deep Reference: Role Access

  • Customer DB role
    • Read access to permitted workspace schemas.
    • DDL and DML on storage.*.
  • Runtime role
    • 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/ingestion/provision again.
  • Branch lifecycle is platform-managed for this tenant model.
  • query_customer_db accepts a single SQL statement. Do not prepend SET search_path; schema-qualify table names instead.