Quickstart

Quickstart

Register an agent and get your first AIGW access token in four requests.

Checked against the Evaluation environment, Console 0.10.1 / 0.14.1, on October 19, 2026. Release status

This guide takes the agent developer's path only. You will discover the authorization server for a Resource, register a client, send a user through sign-in with PKCE, and exchange the code for an AIGW access token. To see how the token reaches a merchant API, read How AIGW works after this.

Want to watch it run first?

The Playground runs this exact flow in your browser against a preconfigured Resource and shows every request and response. Playground guide

Before you start

  • Console access. Sign in to the AIGW Console. If you can't create an account there, request evaluation access and we'll set one up. Unverified Self-serve sign-up has not been confirmed for this release.
  • A Project with a Resource. Create both in the Console and copy the Resource ID. A Resource represents the merchant API your agent will reach. Setup is in Console configuration.
  • An HTTPS redirect URI. Registration only accepts HTTPS. For local work, open a tunnel such as cloudflared tunnel --url http://localhost:8787 and use the URL it prints. Nothing needs to run behind the tunnel for this guide; you will read the code from the browser's address bar.
  • Tools. curl and Node.js 18 or later.
EnvironmentHost
Consolehttps://aigw.eval.loginid.ai
Gateway APIhttps://api.aigw.eval.loginid.ai
Token endpointhttps://core.api.aigw.eval.loginid.ai/oauth2/token
Playgroundhttps://playground.aigw.eval.loginid.ai/

Set your variables

Every command below reads these from your shell.

Shellbash
# Values from your Console Project. RESOURCE_ID is on the Resource page.export RESOURCE_ID="<your-resource-id>"export AIGW="https://api.aigw.eval.loginid.ai"export CORE="https://core.api.aigw.eval.loginid.ai"# Any HTTPS URL you control. For local work, use the tunnel URL below.export REDIRECT_URI="https://<your-tunnel>.trycloudflare.com/callback"

Discover the authorization server

Fetch the Resource's OAuth discovery document. Read endpoints from it rather than hard-coding them: the authorization endpoint is per Resource, while the token endpoint and issuer live on the core host.

Requestbash
curl -s "$AIGW/$RESOURCE_ID/.well-known/openid-configuration"
Response (abbreviated example)200 OKjson
{  "issuer": "<core issuer>",  "authorization_endpoint": "https://api.aigw.eval.loginid.ai/<RESOURCE_ID>/oauth2/auth",  "token_endpoint": "https://core.api.aigw.eval.loginid.ai/oauth2/token",  "jwks_uri": "<core JWKS URL>"}

Register your agent

Dynamic Client Registration (RFC 7591) gives your agent its own client. Register once per agent install, then store the credentials.

Requestbash
curl -s -X POST "$AIGW/api/register" \  -H "Content-Type: application/json" \  -d '{    "client_name": "My agent",    "redirect_uris": ["'"$REDIRECT_URI"'"],    "grant_types": ["authorization_code", "refresh_token"],    "response_types": ["code"],    "token_endpoint_auth_method": "client_secret_post"  }'
Response (abbreviated example)201 Createdjson
{  "client_id": "<client_id>",  "client_secret": "<client_secret>",  "client_secret_expires_at": 0,  "redirect_uris": ["https://<your-tunnel>.trycloudflare.com/callback"],  "token_endpoint_auth_method": "client_secret_post",  "verification_method": "none"}

Save the values: export CLIENT_ID=… and export CLIENT_SECRET=…. The secret does not expire (client_secret_expires_at: 0), so treat it like a long-lived API key.

Do not send resource scopes at registration. Scopes belong on the authorization request in the next step.

Send the user to authorize, with PKCE

Generate a PKCE verifier and state, then build the authorization URL.

pkce.mjsjavascript
// pkce.mjs  (Node.js 18 or later)import { createHash, randomBytes } from "node:crypto";const b64url = (buf) => buf.toString("base64url");const verifier = b64url(randomBytes(32));const challenge = b64url(createHash("sha256").update(verifier).digest());const state = b64url(randomBytes(16));const url = new URL(`${process.env.AIGW}/${process.env.RESOURCE_ID}/oauth2/auth`);url.search = new URLSearchParams({  response_type: "code",  client_id: process.env.CLIENT_ID,  redirect_uri: process.env.REDIRECT_URI,  scope: "openid search:read", // use a scope configured on your Resource  state,  code_challenge: challenge,  code_challenge_method: "S256",}).toString().replace(/\+/g, "%20");console.log(`export CODE_VERIFIER=${verifier}`);console.log(`export STATE=${state}`);console.log(`\nOpen this URL:\n${url}`);
Run itbash
node pkce.mjs

Run the two export lines it prints, then open the URL. The user signs in with the merchant's identity provider and approves. The browser lands on your redirect URI with ?code=…&state=…. Confirm state matches $STATE, then export CODE=….

A new Project approves every agent by default. If your Project's agent policy holds new agents as Pending, approve this one in the Console under Agents before you retry.

Exchange the code for tokens

Post the code to the core token endpoint with the same redirect URI and your PKCE verifier. Send the client secret in the body.

Requestbash
curl -s -X POST "$CORE/oauth2/token" \  -H "Content-Type: application/x-www-form-urlencoded" \  --data-urlencode "grant_type=authorization_code" \  --data-urlencode "code=$CODE" \  --data-urlencode "redirect_uri=$REDIRECT_URI" \  --data-urlencode "client_id=$CLIENT_ID" \  --data-urlencode "client_secret=$CLIENT_SECRET" \  --data-urlencode "code_verifier=$CODE_VERIFIER"
Response (abbreviated example)200 OKjson
{  "access_token": "<AIGW access token, a JWT>",  "id_token": "<ID token>",  "refresh_token": "<refresh token>",  "scope": "openid search:read"}

The access_token is your AIGW token. Your agent sends it as a bearer token to the MCP or UCP service. Keep the id_token out of logs: it carries personal data about the user.

Check your token

Decode the payload locally to confirm who and what the token is for.

Decodebash
export ACCESS_TOKEN="<access_token from the last step>"node -e 'const p=process.argv[1].split(".")[1];console.log(JSON.stringify(JSON.parse(Buffer.from(p,"base64url")),null,2))' "$ACCESS_TOKEN"
Claims (example shape)json
{  "iss": "<core issuer>",  "aud": ["<resource indicator>"],  "sub": "sub_<opaque id>",  "ext": {    "acr": "<...>:al2",    "amr": ["mfa", "kba"],    "agent": { "...": "the agent this token was issued to" },    "project_id": "<your project id>"  }}

aud is the Resource indicator the token is bound to, sub is an opaque user id, and ext records how the user authenticated and which agent acted. Full claim reference: Token endpoint.

If something fails

SymptomLikely causeFix
Registration rejects the redirect URIThe URI is not HTTPSStart a tunnel and register again with its https URL.
Sign-in finishes but no code arrivesThe agent is Pending under the Project's agent policyApprove the agent in Console, Agents, then restart the authorize step.
Token request rejects the clientThe agent was registered with client_secret_basic, which is Unsupported for agents in this releaseRegister again with client_secret_post and send client_id and client_secret in the form body.
invalid_grantCode reused or expired, verifier mismatch, or a different redirect URIRun pkce.mjs again for a fresh verifier and code, and reuse the exact registered redirect URI.

More cases, including Keycloak user mapping, are in Troubleshooting.

Next steps