K

Connect company data with a connector

How to query a database your company already uses from your app — only within the approved scope, through safe queries.

A connector is the safe path from a database your company uses into your app.
Once access is approved you query it straight from app code — AxHub holds the credentials, so your code never contains the company DB password.

What you need

  • An approved connector — a company admin has to register the connection and approve access (a grant) for your account. If you don't have one, ask an admin (Register and approve connectors)
  • The SDK — start with Install the SDK

Check which connectors you can use

First see whether you're approved, and what name to call it by.

axhub connectors mine                      # connectors you can query
axhub connectors resources <connector_id>  # that connector's resource tree

An empty list means approval hasn't happened yet — a connector without a grant doesn't even appear in the list.

Querying from your app

Always pass values through params. Splicing user input into the SQL string opens you to attacks that smuggle commands in through values.

PostgreSQL connectors use $1 and $2 as placeholders — a ? produces a 500 from the backend. Include the schema in table names, as in public..

If you built from a template

The Next.js and Astro templates already ship a query helper. All you need is the connector's name.

import { queryConnector } from '@/lib/axhub-server';

const { rows } = await queryConnector<{ id: number; name: string }>({
  connector: 'my-db',   // the connector's name — not a UUID
  sql: 'SELECT id, name FROM public.employees WHERE active = $1 LIMIT $2',
  params: [true, 100],
});

That single call does find the connector → open a session → query → close the session. Without permission you get a PermissionDeniedError (403); an expired session throws UnauthenticatedError (401).

Querying it yourself

Without the helper, you walk the three steps yourself. A gateway session is a temporary channel saying "I'd like to query through this connection for a while" — it closes automatically after 8 hours.

const gw = sdk.tenant(tenantId).gateway;   // ← the company UUID, not the slug

const session = await gw.sessions.create({ connectorId: 'con_1' });
try {
  const { rows } = await gw.query.run({
    sessionId: session.id,
    sql: 'SELECT id, name FROM public.employees WHERE active = $1 LIMIT $2',
    params: [true, 10],
  });
} finally {
  await gw.sessions.end(session.id);
}

The gateway accepts the company only as a UUID — a slug gives you 400 invalid_format. Find the UUID in tenants from sdk.identity.me().

Check which connectors and resources you can reach with gw.me.connectors() and gw.me.connectorResources(connectorId).

From the terminal, the same thing looks like this.

axhub gateway session start --connector-id <connector_id>
axhub gateway query --session-id <session_id> \
  --sql 'SELECT id, name FROM public.employees LIMIT 10' --execute
axhub gateway session end <session_id>

For connectors pointing at a REST API, a document store, or Google Drive rather than a DB, call axhub gateway invoke, document-invoke, or file-invoke.

When you get stuck

SituationWhat it means
axhub connectors mine is emptyYou have no grant yet — ask an admin to approve one
403 scope_requires_targetIt's a scoped grant. Query an approved resource by name instead of running free-form SQL
403 scope_out_of_rangeThe resource is outside the approved scope
403 PermissionDeniedErrorThe preset doesn't allow that action. The default read-only preset passes only SELECT, WITH, and EXPLAIN
400 invalid_formatYou passed the company as a slug — it has to be a UUID

Every query is written to the audit log along with whether it was allowed or denied.

You've succeeded when

axhub connectors mine shows the connector, and your query comes back with rows.

Next, Manage deployments covers deploy status, logs, and rolling back.