Appearance
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
| Placeholder | Meaning |
|---|---|
REGION | Region label, e.g. au |
ACCOUNT_ID | Account id: 3–15 chars, a–z and 0–9 only |
SERVICE_ID | Service identifier (appears after -- in the tenant hostname) |
CLIENT_ID / CLIENT_SECRET | OAuth client credential from the console |
SERVICE_KEY | Full service key string xg3_sk_{keyId}.{secret} |
Tenant hostname pattern:
text
https://{ACCOUNT_ID}--{SERVICE_ID}.{REGION}.xg3.ioExample: 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):
| Path | Purpose |
|---|---|
POST /oauth/token | Mint JWT access tokens |
GET /.well-known/jwks.json | Regional signing keys (optional offline JWT validation) |
POST /enroll | Agent enrollment (used by the agent) |
GET /enroll/status | Agent enrollment status |
POST /csr | Agent 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/tokenMinting 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 beclient_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
| Header | Meaning |
|---|---|
X-Xg3-Request-Id | Unique request id — use with console Request Lookup |
X-Xg3-Status | Present on many gateway-generated errors |
Content-Type: application/vnd.xg3.error+json | Structured 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.
Related
- Request logging — what xgress3 records for tenant traffic
- Deny codes — interpret 502 error JSON
- Authentication — create credentials and service keys
- Troubleshooting — diagnose failed requests
- Quickstart — first-time setup
- .NET client (Xg3.Auth) — NuGet package that implements this contract for .NET callers