NubleStation

The Gateway is the single API origin for your org: api.{org}.local. Every SDK call and every nuble command goes through it — it authenticates your API key and forwards the request to the right internal service. You configure it once and then mostly forget it exists.

Get up and running

You don’t write code against the Gateway itself:

  • You never call it directly. The SDKs and the CLI construct, authenticate, and route every request for you.
  • You need exactly two things: the gateway URL (http://api.{org}.local) and an API key (nbl_…) issued in the Console when your app was created.
  • Point everything at the one URL. Each SDK takes the gateway base URL and routes internally:
import { createVaultClient }    from "@nublestation/vault";
import { createBlazeClient }    from "@nublestation/blaze";
import { createIdentityClient } from "@nublestation/identity";

const vault    = createVaultClient({ url: "http://api.clinic.local", apiKey });
const { db }   = createBlazeClient({ baseUrl: "http://api.clinic.local", apiKey, schema });
const identity = createIdentityClient({ url: "http://api.clinic.local", identityUrl, app });

The unified @nublestation/client package wraps all three under a single client — see the SDK overview.

Everyday usage

What a request looks like

If you ever inspect traffic (or use curl), every authenticated request carries your API key:

POST http://api.clinic.local/v1/blaze/tasks
Authorization: Bearer nbl_<key_id>.<secret>

How paths map to services

The first segment after /v1/ picks the service:

Path prefixGoes toAuth
/v1/auth/*IdentitySession cookie (no API key)
/v1/blaze/* (legacy /v1/db/*)BlazeAPI key
/v1/vault/*VaultAPI key (+ session cookie for per-user access)
/v1/orbit/*OrbitAPI key
/vault/* (top-level)Vault public filesNone — Vault checks is_public

What gateway errors mean

When the Gateway itself rejects a request (rather than the service behind it):

StatusBody errorMeaning
401unauthorizedAPI key missing, malformed, wrong secret, revoked, or expired. Always generic — the Gateway never tells you which.
404unknown_serviceThe path prefix doesn’t match any service. Check the path.
502upstream_unavailableThe internal service didn’t respond. Check container health with nuble server status.

Any other status code comes from the target service, passed through unchanged.

Checking it’s up

nuble status        # pings the gateway for every configured profile
GET /healthz   → 200 OK (liveness)
GET /readyz    → 200 OK (readiness)

Reference

MethodPathOne-liner
ALL/v1/auth/*Forwarded to Identity verbatim, cookies relayed both ways
ALL/v1/blaze/*Database operations (also accepts legacy /v1/db/*)
ALL/v1/vault/*Authenticated file operations
ALL/v1/orbit/*Deploy and rollback
GET/vault/{app_slug}/{collection}/{filename}Public file fetch, no credentials
GET/healthzLiveness probe
GET/readyzReadiness probe

Limits & gotchas

  • Rate limiting is not shipped yet. Per-app requests-per-minute caps (returning 429) are planned for Phase 6.
  • 401 is intentionally uninformative. Wrong key, revoked key, and expired key all look identical — by design, to prevent enumeration. If you get a 401, re-check the full nbl_<key_id>.<secret> string from the Console.
  • You can’t bypass it. Internal services (Blaze, Vault, Orbit, Identity) have no LAN-exposed ports. Calling them directly from your machine will simply fail to connect.
  • One origin, no CORS hell. Everything lives at api.{org}.local — don’t hardcode per-service URLs anywhere.

Go deeper

How the Gateway resolves keys (Redis cache, Argon2id verification) and how it cryptographically signs forwarded requests is covered in the concepts and security sections: