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

# Exchange Code for Token

> Exchange an authorization code for v2 ID and access tokens using your app credentials.

Exchanges an authorization code for an access token and an ID token, following the OIDC standard. Call it from your backend, because it needs the App Secret.

<Info>
  Send parameters as `application/x-www-form-urlencoded` and authenticate with your App ID and App Secret: HTTP Basic (`client_secret_basic`, recommended) or form fields (`client_secret_post`). Public clients without a secret (`none`) are not supported.
</Info>

## Request Body

<ParamField body="grant_type" type="string" required default="authorization_code">
  Must be `authorization_code`. Refresh tokens are not issued.
</ParamField>

<ParamField body="code" type="string" required>
  The authorization code received on your redirect URI. Single-use, 5-minute lifetime.
</ParamField>

<ParamField body="redirect_uri" type="string" required>
  Must exactly match the redirect URI used in the authorization request.
</ParamField>

<ParamField body="code_verifier" type="string">
  Required only if you sent `code_challenge` on the authorization request (PKCE, `S256`).
</ParamField>

## Response

<ResponseField name="access_token" type="string">
  Bearer token for the `/userinfo` endpoint. Valid for 10 minutes.
</ResponseField>

<ResponseField name="token_type" type="string" default="Bearer">
  Always `Bearer`.
</ResponseField>

<ResponseField name="expires_in" type="number">
  Access token lifetime in seconds (`600`).
</ResponseField>

<ResponseField name="id_token" type="string">
  A signed JWT with authentication context only: `sub`, `iss`, `aud`, `iat`, `exp`, `nonce`, plus `acr`, `hopae_loa`, `hopae_loa_label`, and `hopae_verification` (`provider_id`, `connection_id`). Personal data is never in the ID token. Read it from `/userinfo`.
</ResponseField>

<ResponseField name="scope" type="string">
  The granted scopes.
</ResponseField>

<RequestExample>
  ```bash theme={null}
  curl --request POST \
    --url 'https://connect.hopae.com/v2/token' \
    --user '{appId}:{appSecret}' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data 'grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "access_token": "<opaque access token>",
    "token_type": "Bearer",
    "expires_in": 600,
    "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "scope": "openid hopae"
  }
  ```
</ResponseExample>

## ID token claims

```json Decoded id_token payload theme={null}
{
  "sub": "019bc4f2-8a31-7c5e-9d02-4f7a1b3e60d8",
  "iss": "https://connect.hopae.com",
  "aud": "xhdh8a13",
  "iat": 1788427192,
  "exp": 1788428992,
  "nonce": "n-0S6_WzA2Mj",
  "acr": "urn:hopae:loa:4",
  "hopae_loa": 4,
  "hopae_loa_label": "high",
  "hopae_verification": {
    "provider_id": "smart-id",
    "connection_id": "smart-id"
  }
}
```

* `sub` is the verification id, a new value for every verification, not a stable user identifier.
* `hopae_verification.provider_id` and `hopae_verification.connection_id` identify the connection that ran (catalog ids). They are nested under `hopae_verification`, not top-level claims. There is no `amr` claim on v2 tokens.
* `iss` is `https://connect.hopae.com`. Validate it, and verify `aud` against your App ID. Keys are at [`/jwks`](/v2/api-reference/oidc/jwks).
* ID tokens are valid for 30 minutes.


## OpenAPI

````yaml POST /token
openapi: 3.0.0
info:
  title: hConnect API
  description: >-
    The hConnect API provides a unified interface for electronic identity
    verification across multiple eID providers globally.
  version: 1.0.0
  contact:
    name: hConnect Support
    url: https://www.hopae.com
    email: support@hopae.com
servers:
  - url: https://sandbox.api.hopae.com/connect
    description: Sandbox Server
security: []
tags:
  - name: Console - API Keys
    description: Workspace API key management (Console)
  - name: Providers
    description: eID provider discovery
  - name: Token
    description: OAuth 2.0 token exchange
  - name: Verifications
    description: Identity verification sessions
  - name: Workspace API - Activation
    description: Provider activation per app
  - name: Workspace API - Apps
    description: App management
  - name: Workspace API - Production Tests
    description: Production test challenges
  - name: Workspace API - Workflows
    description: Workflow configuration per app
  - name: Workspace API - Workspace
    description: Workspace information
paths:
  /token:
    post:
      tags:
        - Token
      summary: Exchange Code for Token
      description: >-
        Exchanges an authorization code for an ID token, following the OAuth 2.0
        standard.
      operationId: exchangeCodeForToken
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
      responses:
        '200':
          description: Token exchange successful.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id_token:
                    type: string
                    description: A JWT containing the user's verified claims.
        '400':
          description: Bad Request - Invalid grant_type or missing parameters.
        '401':
          description: Unauthorized - Invalid code or client credentials.
      security: []
components:
  schemas:
    TokenRequest:
      type: object
      properties:
        grant_type:
          type: string
          enum:
            - authorization_code
          description: Must be 'authorization_code'.
        code:
          type: string
          description: The authorization code received after a successful verification.
        client_id:
          type: string
          description: Your application's Client ID.
        client_secret:
          type: string
          description: Your application's Client Secret. Required for confidential clients.
      required:
        - grant_type
        - code
        - client_id

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.