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

# Exchange Credentials for a User API Key

> GET /authenticate/apikeyexchange — Trade your Portal.io username and password for a User API Key required for all subsequent HMAC-authenticated requests.

The API key exchange endpoint authenticates your Portal.io credentials and returns a `meta.apiKey` value you must include in the `X-MSS-API-USERKEY` header on all subsequent requests. This is the entry point for every integration: call it once to obtain the key, then use that key to sign all other requests.

<Note>
  For the initial exchange, `X-MSS-API-USERKEY` must be an empty string and is **excluded** from the HMAC canonical message. The canonical message is: `[HTTP method][base URL without query params][timestamp]` — no content-type (GET request) and no user key. See the [signing guide](/authentication/signing-requests#get-request-credential-exchange) for a worked example.
</Note>

<RequestExample>
  ```bash curl theme={null}
  curl -i -X GET \
    "https://sandbox.api.portal.io/authenticate/apikeyexchange?UserName=user%40example.com&Password=MyP%40ss123" \
    -H "Accept: application/json" \
    -H "X-MSS-API-APPID: YOUR_APP_ID" \
    -H "X-MSS-API-USERKEY: " \
    -H "X-MSS-CUSTOM-DATE: Mon, 06 Apr 2026 00:22:19 GMT" \
    -H "X-MSS-SIGNATURE: BASE64_SIGNATURE"
  ```

  ```python python theme={null}
  import requests
  from portal_auth import sign_request  # See authentication guide

  url = "https://sandbox.api.portal.io/authenticate/apikeyexchange?UserName=user%40example.com&Password=MyP%40ss123"
  timestamp = "Mon, 06 Apr 2026 00:22:19 GMT"
  signature = sign_request("GET", url, "", timestamp, "", "YOUR_SECRET_KEY")

  response = requests.get(url, headers={
      "Accept": "application/json",
      "X-MSS-API-APPID": "YOUR_APP_ID",
      "X-MSS-API-USERKEY": "",
      "X-MSS-CUSTOM-DATE": timestamp,
      "X-MSS-SIGNATURE": signature
  })
  print(response.json())
  ```

  ```javascript node.js theme={null}
  const { signRequest } = require('./portalAuth'); // See authentication guide

  const url = "https://sandbox.api.portal.io/authenticate/apikeyexchange?UserName=user%40example.com&Password=MyP%40ss123";
  const timestamp = new Date().toUTCString();
  const signature = signRequest("GET", url, "", timestamp, "", "YOUR_SECRET_KEY");

  const response = await fetch(url, {
      headers: {
          "Accept": "application/json",
          "X-MSS-API-APPID": "YOUR_APP_ID",
          "X-MSS-API-USERKEY": "",
          "X-MSS-CUSTOM-DATE": timestamp,
          "X-MSS-SIGNATURE": signature
      }
  });
  const data = await response.json();
  console.log(data);
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "userId": "string",
    "sessionId": "string",
    "userName": "string",
    "displayName": "string",
    "bearerToken": "string",
    "refreshToken": "string",
    "refreshTokenExpiry": "2026-04-06T00:22:19Z",
    "profileUrl": "string",
    "roles": ["string"],
    "permissions": ["string"],
    "authProvider": "string",
    "meta": {
      "apiKey": "YOUR_USER_API_KEY"
    }
  }
  ```
</ResponseExample>


## OpenAPI

````yaml GET /authenticate/apikeyexchange
openapi: 3.1.0
info:
  title: Portal.Api
  version: '1.0'
servers:
  - url: http://127.0.0.1:5000
security: []
tags: []
paths:
  /authenticate/apikeyexchange:
    get:
      tags:
        - Authentication
      summary: Authenticate User & Get User Token
      description: >-
        Exchange your Portal username and password for a User API Key. Send the
        HMAC authentication headers with this request to obtain the key.
      operationId: ExchangeApiKey
      parameters:
        - $ref: '#/components/parameters/Accept'
        - name: X-MSS-API-APPID
          in: header
          description: Application Id
          required: true
          schema:
            type: string
        - name: X-MSS-CUSTOM-DATE
          in: header
          description: A date timestamp of the request
          required: true
          schema:
            type: string
        - name: X-MSS-SIGNATURE
          in: header
          description: A signature for the request
          required: true
          schema:
            type: string
        - name: X-MSS-API-USERKEY
          in: header
          description: User API Key
          required: true
          schema:
            type: string
        - name: UserName
          in: query
          description: user email address
          required: true
          schema:
            type: string
            maxLength: 256
        - name: Password
          in: query
          description: user password
          required: true
          schema:
            type: string
            format: password
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthenticateResponse'
        '401':
          description: Invalid credentials or User Email is not verified
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebServiceException'
      deprecated: false
      x-codeSamples: []
components:
  parameters:
    Accept:
      name: Accept
      in: header
      description: Accept Header
      required: true
      schema:
        type: string
        enum:
          - application/json
  schemas:
    AuthenticateResponse:
      title: AuthenticateResponse
      properties:
        userId:
          type: string
        sessionId:
          type: string
        userName:
          type: string
        displayName:
          type: string
        referrerUrl:
          type: string
        bearerToken:
          type: string
        refreshToken:
          type: string
        refreshTokenExpiry:
          type: string
          format: date-time
        profileUrl:
          type: string
        roles:
          type: array
          items:
            type: string
        permissions:
          type: array
          items:
            type: string
        authProvider:
          type: string
        responseStatus:
          $ref: '#/components/schemas/ResponseStatus'
        meta:
          $ref: '#/components/schemas/Dictionary_String_String_'
      description: AuthenticateResponse
      type: object
    WebServiceException:
      title: WebServiceException
      properties:
        statusCode:
          type: integer
          format: int32
        statusDescription:
          type: string
        responseHeaders:
          $ref: '#/components/schemas/WebHeaderCollection'
        responseDto:
          $ref: '#/components/schemas/Object'
        responseBody:
          type: string
        message:
          type: string
        errorCode:
          type: string
        errorMessage:
          type: string
        serverStackTrace:
          type: string
        state:
          $ref: '#/components/schemas/Object'
        responseStatus:
          $ref: '#/components/schemas/ResponseStatus'
        targetSite:
          $ref: '#/components/schemas/MethodBase'
        data:
          $ref: '#/components/schemas/IDictionary'
        innerException:
          $ref: '#/components/schemas/Exception'
        helpLink:
          type: string
        source:
          type: string
        hResult:
          type: integer
          format: int32
        stackTrace:
          type: string
      description: WebServiceException
      type: object
    ResponseStatus:
      title: ResponseStatus
      properties:
        errorCode:
          type: string
        message:
          type: string
        stackTrace:
          type: string
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ResponseError'
        meta:
          $ref: '#/components/schemas/Dictionary_String_String_'
      description: ResponseStatus
      type: object
    Dictionary_String_String_:
      title: Dictionary<String,String>
      additionalProperties:
        type: string
      description: Dictionary<String,String>
      type: object
    WebHeaderCollection:
      title: WebHeaderCollection
      properties: {}
      description: WebHeaderCollection
      type: object
    Object:
      properties: {}
      description: Object
      type: object
    MethodBase:
      title: MethodBase
      properties: {}
      description: MethodBase
      type: object
    IDictionary:
      title: IDictionary
      properties: {}
      description: IDictionary
      type: object
    Exception:
      title: Exception
      properties: {}
      description: Exception
      type: object
    ResponseError:
      title: ResponseError
      properties:
        errorCode:
          type: string
        fieldName:
          type: string
        message:
          type: string
        meta:
          $ref: '#/components/schemas/Dictionary_String_String_'
      description: ResponseError
      type: object

````