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 treeAn 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
| Situation | What it means |
|---|---|
axhub connectors mine is empty | You have no grant yet — ask an admin to approve one |
403 scope_requires_target | It's a scoped grant. Query an approved resource by name instead of running free-form SQL |
403 scope_out_of_range | The resource is outside the approved scope |
403 PermissionDeniedError | The preset doesn't allow that action. The default read-only preset passes only SELECT, WITH, and EXPLAIN |
400 invalid_format | You 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.