Skip to content

HTTP ingress and authentication

This guide shows how to call your service hostname with cURL for each supported caller authentication mode. You need your account ID, service ID, regional hostname, and either a credential (JWT) or service key from the console.

A service may allow JWT only, service key only, or both. Do not send non-empty X-Xg3-Authorization and X-Xg3-Service-Key on the same request — that combination is rejected.

All examples use curl from a shell. On Windows, use the same flags in PowerShell or Git Bash.

Calling from .NET? The Xg3.Auth NuGet package implements this contract for you — token refresh, header attachment, and tenant hostname handling in a few lines, for HttpClient, Refit, Flurl, or RestSharp.

Placeholders

PlaceholderMeaning
REGIONRegion label, e.g. au
ACCOUNT_IDAccount id: 3–15 chars, az and 09 only
SERVICE_IDService identifier (appears after -- in the tenant hostname)
CLIENT_ID / CLIENT_SECRETOAuth client credential from the console
SERVICE_KEYFull service key string xg3_sk_{keyId}.{secret}

Tenant hostname pattern:

text
https://{ACCOUNT_ID}--{SERVICE_ID}.{REGION}.xg3.io

Example: https://acme--api.au.xg3.io


Service ingress URL shape

Tenant relay: Send requests to:

text
https://{accountId}--{serviceId}.{region}.xg3.io/{path}?{query}

The full path and query string are forwarded to your backend unchanged. For example:

text
https://acme--api.au.xg3.io/api/v1/widgets?q=1

→ your backend receives path /api/v1/widgets and query ?q=1.

Platform REST on the regional apex host https://{region}.xg3.io (no account--service prefix):

PathPurpose
POST /oauth/tokenMint JWT access tokens
GET /.well-known/jwks.jsonRegional signing keys (optional offline JWT validation)
POST /enrollAgent enrollment (used by the agent)
GET /enroll/statusAgent enrollment status
POST /csrAgent certificate signing

JWT-protected services

Services that allow JWT require X-Xg3-Authorization: Bearer … on ingress. Tokens are minted at:

text
POST https://{region}.xg3.io/oauth/token

Minting is only allowed when the service’s authentication modes include JWT.

Scope string

Token requests include a scope string (space-separated key:value pairs). Include account:ACCOUNT_ID and service:SERVICE_ID exactly once each. Order does not matter.

The account in scope must match the credential’s account. The service must appear on the credential’s allowed services list in the console.

Token request — JSON body

bash
curl -sS -X POST "https://REGION.xg3.io/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "CLIENT_ID",
    "client_secret": "CLIENT_SECRET",
    "scope": "account:ACCOUNT_ID service:SERVICE_ID"
  }'

Successful response (HTTP 200):

json
{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Save the token (example with jq):

bash
ACCESS_TOKEN=$(curl -sS -X POST "https://REGION.xg3.io/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "CLIENT_ID",
    "client_secret": "CLIENT_SECRET",
    "scope": "account:ACCOUNT_ID service:SERVICE_ID"
  }' | jq -r .access_token)

Token request — form URL-encoded

bash
curl -sS -X POST "https://REGION.xg3.io/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=CLIENT_ID" \
  --data-urlencode "client_secret=CLIENT_SECRET" \
  --data-urlencode "scope=account:ACCOUNT_ID service:SERVICE_ID"

Notes

  • If you send grant_type, it must be client_credentials.
  • Failures return OAuth-shaped JSON (error, error_description) with an appropriate HTTP status.
  • Tokens are short-lived (default 3600 seconds). Plan refresh before expiry.
  • Token audience matches your tenant hostname: https://{ACCOUNT_ID}--{SERVICE_ID}.{REGION}.xg3.io.

Ingress request — Bearer token

After obtaining a token:

bash
curl -sS -D - "https://ACCOUNT_ID--SERVICE_ID.REGION.xg3.io/api/v1/health" \
  -H "X-Xg3-Authorization: Bearer ${ACCESS_TOKEN}"

JSON POST example:

bash
curl -sS -D - "https://ACCOUNT_ID--SERVICE_ID.REGION.xg3.io/api/v1/widgets" \
  -H "X-Xg3-Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"name":"example"}'

The standard Authorization header is not consumed for gateway authentication. If present, it is forwarded to your backend unchanged.


Service-key-protected services

Send the full key on every request:

http
X-Xg3-Service-Key: xg3_sk_{keyId}.{secret}
bash
curl -sS -D - "https://ACCOUNT_ID--SERVICE_ID.REGION.xg3.io/api/v1/health" \
  -H "X-Xg3-Service-Key: SERVICE_KEY"

There is no token endpoint for this mode. The key must be on the service key’s allowed services list in the console.


JWKS (optional)

Fetch regional signing keys for offline JWT validation or inspection:

bash
curl -sS "https://REGION.xg3.io/.well-known/jwks.json"

Ingress authorization is still enforced by xgress3 on every request. JWKS supports custom validators or debugging.

Browsers and client certificates

Opening platform URLs such as /.well-known/jwks.json in a web browser may show a client certificate picker. That is expected and does not mean JWKS requires a certificate.

The regional gateway serves public platform REST (JWKS, OAuth token, enrollment) and agent traffic on the same HTTPS port. When agent mTLS is enabled, the TLS handshake may offer optional client certificates so agents can authenticate. Browsers often prompt when they see that offer; curl and other HTTP clients do not and work without a client cert.

JWKS, /oauth/token, and enrollment paths do not require a client certificate. Cancel or dismiss the browser prompt, or use curl (as above) to fetch JWKS. Agents present a client certificate only on their tunnel connection, not for these public REST paths.


Response headers

HeaderMeaning
X-Xg3-Request-IdUnique request id — use with console Request Lookup
X-Xg3-StatusPresent on many gateway-generated errors
Content-Type: application/vnd.xg3.error+jsonStructured error body from the gateway

Every successful response should include X-Xg3-Request-Id.

Authentication headers (X-Xg3-Authorization, X-Xg3-Service-Key) are not stored in Request Lookup records. See Request logging.