> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grantex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Agent Authorization Quickstart

> Implement AI agent authorization with Grantex: register an agent, request consent, exchange a code, verify a JWT grant, and write audit records.

## 1. Install the SDK

This guide targets TypeScript `0.3.13`, Python `0.3.14`, Go `v0.1.10`
(which requires Go 1.26.1+), and MCP Auth `2.0.2`.
See [Release Status](/release-status) for publication details and upgrade guidance.

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install @grantex/sdk@0.3.13
  ```

  ```bash Python theme={null}
  python -m pip install grantex==0.3.14
  ```

  ```bash Go theme={null}
  go get github.com/mishrasanjeev/grantex-go@v0.1.10
  ```

  ```bash CLI theme={null}
  npm install -g @grantex/cli
  grantex config set --url https://api.grantex.dev --key YOUR_API_KEY
  ```
</CodeGroup>

## 2. Register your agent

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Grantex } from '@grantex/sdk';

  const grantex = new Grantex({ apiKey: process.env.GRANTEX_API_KEY });

  const agent = await grantex.agents.register({
    name: 'travel-booker',
    description: 'Books flights and hotels on behalf of users',
    scopes: ['calendar:read', 'payments:initiate:max_500', 'email:send'],
  });

  console.log(agent.did);
  // → did:grantex:ag_01HXYZ123abc...
  ```

  ```python Python theme={null}
  import os

  from grantex import Grantex

  client = Grantex(api_key=os.environ["GRANTEX_API_KEY"])

  agent = client.agents.register(
      name="travel-booker",
      scopes=["calendar:read", "payments:initiate:max_500", "email:send"],
      description="Books flights and hotels on behalf of users",
  )

  print(agent.did)
  # → did:grantex:ag_01HXYZ123abc...
  ```

  ```go Go theme={null}
  ctx := context.Background()
  client := grantex.NewClient(os.Getenv("GRANTEX_API_KEY"))

  agent, err := client.Agents.Register(ctx, grantex.RegisterAgentParams{
      Name:        "travel-booker",
      Description: "Books flights and hotels on behalf of users",
      Scopes:      []string{"calendar:read", "payments:initiate:max_500", "email:send"},
  })
  if err != nil {
      log.Fatal(err)
  }

  const didPrefix = "did:grantex:"
  if !strings.HasPrefix(agent.DID, didPrefix) {
      log.Fatal("unexpected agent DID")
  }
  agentID := strings.TrimPrefix(agent.DID, didPrefix)
  fmt.Printf("%s (%s)\n", agentID, agent.DID)
  ```

  ```bash CLI theme={null}
  grantex agents register \
    --name travel-booker \
    --description "Books flights and hotels on behalf of users" \
    --scopes calendar:read,payments:initiate:max_500,email:send
  ```
</CodeGroup>

<Note>
  Go SDK `v0.1.10` expects an `id` response field while the current API returns
  `agentId`, so `agent.ID` is empty after registration. The Go example derives
  `agentID` from the stable `did:grantex:<agentId>` value until a corrected SDK
  release is published. Add `strings` to your imports.
</Note>

## 3. Request authorization from a user

<CodeGroup>
  ```typescript TypeScript theme={null}
  const authRequest = await grantex.authorize({
    agentId: agent.id,
    userId: 'user_abc123',
    scopes: ['calendar:read', 'payments:initiate:max_500'],
    expiresIn: '24h',
    redirectUri: 'https://yourapp.com/auth/callback',
  });

  // Redirect user to the consent page
  console.log(authRequest.consentUrl);
  // → https://consent.grantex.dev/authorize?req=eyJ...
  ```

  ```python Python theme={null}
  from grantex import AuthorizeParams

  auth = client.authorize(AuthorizeParams(
      agent_id=agent.id,
      user_id="user_abc123",
      scopes=["calendar:read", "payments:initiate:max_500"],
  ))

  # Redirect user to the consent page
  print(auth.consent_url)
  ```

  ```go Go theme={null}
  authRequest, err := client.Authorize(ctx, grantex.AuthorizeParams{
      AgentID:     agentID,
      PrincipalID: "user_abc123",
      Scopes:      []string{"calendar:read", "payments:initiate:max_500"},
      ExpiresIn:   "24h",
      RedirectURI: "https://yourapp.com/auth/callback",
  })
  if err != nil {
      log.Fatal(err)
  }

  // Redirect the user to the consent page.
  fmt.Println(authRequest.ConsentURL)
  ```

  ```bash CLI theme={null}
  grantex authorize \
    --agent ag_01HXYZ... \
    --principal user_abc123 \
    --scopes calendar:read,payments:initiate:max_500
  # Sandbox mode returns the code directly
  ```
</CodeGroup>

## 4. Exchange the code for a grant token

After the user approves, your redirect URI receives an authorization `code`. Exchange it for a signed grant token:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const token = await grantex.tokens.exchange({
    code,                  // from the redirect callback
    agentId: agent.id,
  });

  console.log(token.grantToken);  // RS256 JWT — pass this to your agent
  console.log(token.scopes);      // ['calendar:read', 'payments:initiate:max_500']
  console.log(token.grantId);     // 'grnt_01HXYZ...'
  ```

  ```python Python theme={null}
  from grantex import ExchangeTokenParams

  token = client.tokens.exchange(ExchangeTokenParams(
      code=code,
      agent_id=agent.id,
  ))

  print(token.grant_token)  # RS256 JWT
  print(token.scopes)       # ('calendar:read', 'payments:initiate:max_500')
  print(token.grant_id)     # 'grnt_01HXYZ...'
  ```

  ```go Go theme={null}
  token, err := client.Tokens.Exchange(ctx, grantex.ExchangeTokenParams{
      Code:    code, // from the redirect callback
      AgentID: agentID,
  })
  if err != nil {
      log.Fatal(err)
  }

  fmt.Println(token.GrantToken)
  fmt.Println(token.Scopes)
  fmt.Println(token.GrantID)
  ```

  ```bash CLI theme={null}
  grantex tokens exchange --code <code> --agent-id ag_01HXYZ...
  # Returns grantToken (JWT), refreshToken, grantId, scopes
  ```
</CodeGroup>

## 5. Verify token signatures and claims locally

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { verifyGrantToken } from '@grantex/sdk';

  const grant = await verifyGrantToken(token.grantToken, {
    jwksUri: 'https://api.grantex.dev/.well-known/jwks.json',
    requiredScopes: ['calendar:read'],
  });

  console.log(grant.principalId); // 'user_abc123'
  console.log(grant.scopes);     // ['calendar:read', 'payments:initiate:max_500']
  ```

  ```python Python theme={null}
  from grantex import verify_grant_token, VerifyGrantTokenOptions

  grant = verify_grant_token(token.grant_token, VerifyGrantTokenOptions(
      jwks_uri="https://api.grantex.dev/.well-known/jwks.json",
  ))

  print(grant.principal_id)  # 'user_abc123'
  print(grant.scopes)        # ('calendar:read', 'payments:initiate:max_500')
  ```

  ```go Go theme={null}
  grant, err := grantex.VerifyGrantToken(ctx, token.GrantToken, grantex.VerifyOptions{
      JwksURI:        "https://api.grantex.dev/.well-known/jwks.json",
      RequiredScopes: []string{"calendar:read"},
  })
  if err != nil {
      log.Fatal(err)
  }

  fmt.Println(grant.PrincipalID) // "user_abc123"
  fmt.Println(grant.Scopes)
  ```

  ```bash CLI theme={null}
  grantex tokens verify <jwt>
  # Shows: valid, grantId, scopes, principal, agent, expiresAt
  ```
</CodeGroup>

<Note>
  Local verification retrieves or reuses the issuer's JWKS and checks the token's
  signature and claims. It does not prove current revocation unless the verifier
  performs an online state check or synchronizes revocation data.
</Note>

## 6. Log every action

<CodeGroup>
  ```typescript TypeScript theme={null}
  await grantex.audit.log({
    agentId: agent.id,
    agentDid: agent.did,
    grantId: token.grantId,
    principalId: 'user_abc123',
    action: 'payment.initiated',
    status: 'success',
    metadata: { amount: 420, currency: 'USD', merchant: 'Air India' },
  });
  ```

  ```python Python theme={null}
  client.audit.log(
      agent_id=agent.id,
      agent_did=agent.did,
      grant_id=token.grant_id,
      principal_id="user_abc123",
      action="payment.initiated",
      status="success",
      metadata={"amount": 420, "currency": "USD", "merchant": "Air India"},
  )
  ```

  ```bash CLI theme={null}
  grantex audit log \
    --agent-id ag_01HXYZ... \
    --agent-did did:grantex:ag_01HXYZ... \
    --grant-id grnt_01HXYZ... \
    --principal-id user_abc123 \
    --action payment.initiated \
    --status success \
    --metadata '{"amount":420,"currency":"USD","merchant":"Air India"}'
  ```
</CodeGroup>

<Warning>
  Go SDK `v0.1.10` cannot send the current audit-log contract: its
  `LogAuditParams` omits the required `agentDid` and `principalId` fields. Use
  the CLI or call `POST /v1/audit/log` directly for this optional step until a
  corrected Go SDK release is published.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="lightbulb" href="/concepts/how-it-works">
    Learn about the three primitives: agent identity, delegated grants, and audit trails.
  </Card>

  <Card title="Local Development" icon="docker" href="/local-development">
    Run the full stack locally with Docker Compose and sandbox mode.
  </Card>

  <Card title="TypeScript SDK" icon="js" href="/sdks/typescript/overview">
    Full API reference for the TypeScript SDK.
  </Card>

  <Card title="Python SDK" icon="python" href="/sdks/python/overview">
    Full API reference for the Python SDK.
  </Card>

  <Card title="Go SDK" icon="code" href="/sdks/go/overview">
    Full API reference for the Go SDK.
  </Card>

  <Card title="CLI" icon="terminal" href="/integrations/cli">
    83 commands with --json support for scripting and AI agents.
  </Card>
</CardGroup>
