Skip to content

HTTPS Data API

Parameterized SQL from runtimes that cannot hold a socket.

View as Markdown

Authenticate

Create a project-bound API key. Reads require db.query.read, writes require db.query.write. Send it from your server as a Bearer token or in x-api-key, never from a browser.

Run a query

Values are passed separately in params. Do not interpolate user input into the SQL string.

typescript
const response = await fetch(
  `${process.env.APP_BASE_URL}/api/v1/databases/${databaseId}/query`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.VELTIC_API_KEY}`
    },
    body: JSON.stringify({
      sql: 'SELECT id, name FROM products WHERE id = $1',
      params: [42],
      method: 'execute'
    })
  }
);
if (!response.ok) throw new Error(`Query failed: ${response.status}`);
const result = await response.json();

Transactions and boundaries

The transaction endpoint accepts between 1 and 25 statements in { statements: [...] } and runs them in one transaction. Separate requests share no session, so LISTEN/NOTIFY, cursors and session-scoped locks need a direct PostgreSQL connection.

bash
POST /api/v1/databases/<databaseId>/transaction

Row level security still applies

Policies are enforced by PostgreSQL, so they apply to Data API calls exactly as they do to a direct connection. The API is a transport, not an authorization bypass.