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:8787and 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.
curland Node.js 18 or later.
| Environment | Host |
|---|---|
| Console | https://aigw.eval.loginid.ai |
| Gateway API | https://api.aigw.eval.loginid.ai |
| Token endpoint | https://core.api.aigw.eval.loginid.ai/oauth2/token |
| Playground | https://playground.aigw.eval.loginid.ai/ |
Set your variables
Every command below reads these from your shell.
# 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.
curl -s "$AIGW/$RESOURCE_ID/.well-known/openid-configuration"{ "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.
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" }'{ "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.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}`);node pkce.mjsRun 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.
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"{ "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.
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"{ "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
| Symptom | Likely cause | Fix |
|---|---|---|
| Registration rejects the redirect URI | The URI is not HTTPS | Start a tunnel and register again with its https URL. |
| Sign-in finishes but no code arrives | The agent is Pending under the Project's agent policy | Approve the agent in Console, Agents, then restart the authorize step. |
| Token request rejects the client | The agent was registered with client_secret_basic, which is Unsupported for agents in this release | Register again with client_secret_post and send client_id and client_secret in the form body. |
invalid_grant | Code reused or expired, verifier mismatch, or a different redirect URI | Run 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.

