> ## 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.

# Authenticate with the Portal.io API

> Portal.io API uses HMAC-SHA256 request signing. Learn how to get your API credentials, exchange them for a User Key, and include auth headers on every request.

Every Portal.io API request must be signed using HMAC-SHA256. Authentication works in two stages: first you exchange your Portal.io username and password for a User API Key, then you include that User Key in the signature of all subsequent requests. There are no session cookies and no OAuth flows — each request is independently authenticated by its signature headers.

## How authentication works

**Step 1 — Exchange credentials for a User Key.**
Call `GET /authenticate/apikeyexchange` with your username and password as query parameters. For this request only, the `X-MSS-API-USERKEY` header is an empty string and is excluded from the HMAC canonical message. A successful response returns a User API Key at `meta.apiKey` in the response body.

**Step 2 — Sign all subsequent requests with the User Key.**
Include your User Key in the `X-MSS-API-USERKEY` header and incorporate it into the HMAC canonical message for every request you make after the initial exchange.

See [Signing requests](/authentication/signing-requests) for the full details on building the canonical message and computing the signature.

## Required headers

Every request to the Portal.io API must include the following headers:

| Header              | Description                                                                                                   | Example                                        |
| ------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| `Accept`            | Must be `application/json`                                                                                    | `application/json`                             |
| `X-MSS-API-APPID`   | Your API Application Key, provided by your Portal.io representative                                           | `D78C5B43-60B7-4F06-9372-0B3F9010D042`         |
| `X-MSS-API-USERKEY` | The User API Key obtained from the credential exchange. Use an empty string for the initial exchange request. | `qBOSOYDeZaSzTxqMCL1Kr66JpU2H6wHCLz7xviZUOcA=` |
| `X-MSS-CUSTOM-DATE` | Current UTC date and time in RFC 7231 format. Must exactly match the timestamp used in your HMAC signature.   | `Mon, 06 Apr 2026 00:22:19 GMT`                |
| `X-MSS-SIGNATURE`   | HMAC-SHA256 of the canonical message, Base64 encoded                                                          | `3Tsd9...`                                     |

## Obtaining credentials

To get your **API Application Key** and **Secret Key**:

1. Create a free sandbox account at [https://sandbox.portal.io](https://sandbox.portal.io) and verify your email address.
2. Contact your Portal.io representative. Let them know you have a sandbox account, and they will provide both keys.

Your **User API Key** is obtained programmatically by calling the `GET /authenticate/apikeyexchange` endpoint with your Portal.io username and password. See the [quickstart](/quickstart) for a full walkthrough with curl examples.

## Common errors

| Status | Cause                                                                                            | Fix                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `401`  | Invalid credentials or unverified email address                                                  | Confirm your username and password are correct. Check that you verified your email after signing up.                                                                                                                                                                                                                                                                                                                                                               |
| `401`  | Signature mismatch (body: `"You are not authorized. Your request signature (hash) is invalid."`) | Ensure the canonical message is assembled in the correct order (see [Signing requests](/authentication/signing-requests)), that you are using the base URL without query parameters, that your timestamp in `X-MSS-CUSTOM-DATE` exactly matches the value in the canonical message, and that you are using the Secret Key as raw ASCII bytes without Base64-decoding it first. For POST requests, confirm the `Content-Type` is included in the canonical message. |
| `403`  | Insufficient permissions                                                                         | The authenticated user does not have permission for the requested resource or action.                                                                                                                                                                                                                                                                                                                                                                              |

For a detailed explanation of how to construct the HMAC signature, see [Signing requests](/authentication/signing-requests).
