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

# Authentication

> HMAC-SHA512 request signing for all Ingo Payments APIs — credentials, signature construction, environments, and product-specific requirements.

All Ingo Payments APIs use **HMAC-SHA512** request signing. This is not an API-key-in-header pattern — every request must be signed using a shared secret that never leaves your server. The `Authorization` header carries the result of that signing process.

<Info>
  Your HMAC credentials are provisioned by your Ingo integration manager at onboarding. You will receive a **username** and a **secret**. The secret is used locally to sign requests and is never transmitted.
</Info>

***

## Product-specific requirements

The signing process is identical across all products. The table below summarizes any additional requirements per product.

| Product                  | Auth mechanism                 | Additional requirement                                                                                          |
| ------------------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| IngoPay API              | HMAC-SHA512                    | —                                                                                                               |
| Notify — Classic         | HMAC-SHA512                    | —                                                                                                               |
| Notify — Managed Parties | HMAC-SHA512                    | —                                                                                                               |
| Embedded Account Capture | HMAC-SHA512 (server-side only) | The iFrame SDK handles browser-side session auth automatically — no additional signing required from the client |
| Banking Platform         | HMAC-SHA512 + API key          | An `api_key` credential must accompany every request (see below)                                                |

### Banking Platform — API key

The Banking Platform requires an additional **API key** on every request alongside the HMAC signature. Both layers are enforced — a valid API key alone will not work without a valid signature.

Pass the API key as a request header (preferred):

```
api_key: YOUR_API_KEY
```

Or as a body field:

```json theme={null}
{
  "api_key": "YOUR_API_KEY",
  ...
}
```

Treat the API key as a secret. Do not expose it in client-side code or commit it to source control.

***

## Credentials

| Credential       | Description                                                               |
| ---------------- | ------------------------------------------------------------------------- |
| `username`       | Identifies your integration in the `Authorization` header                 |
| `secret`         | Used locally to sign each request. Never transmitted.                     |
| `participant_id` | Numeric identifier included in the request body (IngoPay, Notify, iFrame) |

***

## Authorization header format

Every request must include an `Authorization` header in this exact format:

```
hmac username="{username}", algorithm="hmac-sha512", headers="{header_string}", signature="{signature}"
```

**Example:**

```
Authorization: hmac username="test", algorithm="hmac-sha512", headers="request-line x-date content-type content-sha512 content-length", signature="hAMqhSX6eogO1QpES9Dg9WynJWJPNxFLe1wtV4ppfvmGmqpYCiJYm6lqrHNjcmQUZCyMBdK86Zkm+m3BJwj3XA=="
```

| Parameter   | Value                                                   |
| ----------- | ------------------------------------------------------- |
| `username`  | Your Ingo-issued username                               |
| `algorithm` | Always `hmac-sha512`                                    |
| `headers`   | Space-separated list of signed header names (see below) |
| `signature` | Base64-encoded HMAC-SHA512 signature (see below)        |

***

## Building the signature — step by step

<Steps>
  <Step title="Assemble required headers">
    Every request must include these headers. Generate them before signing:

    **`X-Date`** — Current timestamp in GMT/RFC 1123 format. Ingo allows
    a clock skew of ±300 seconds. Requests outside this window are rejected
    to prevent replay attacks. Use `X-Date` rather than `Date` to avoid
    conflicts with HTTP libraries.

    ```
    X-Date: Fri, 17 Jan 2020 19:59:29 GMT
    ```

    **`Content-sha512`** — Base64-encoded SHA-512 hash of the raw request
    body. Ingo uses this to verify body integrity — if the hashes don't
    match, the request is rejected. Use RAW (not hex) output from your
    hashing library before Base64 encoding.

    ```
    Content-sha512: HpXfYk7qDatRNVlGHQOv3ELyAVd+JCdUcpHB5PMnu08EYbfH...
    ```

    **`Content-Length`** — Byte length of the request body.

    ```
    Content-Length: 398
    ```

    **`Content-Type`** — Always `application/json`.

    ```
    Content-Type: application/json
    ```
  </Step>

  <Step title="Build the header string">
    The header string is a space-separated, lowercase list of the header
    names you are signing, in the order they appear in the signature string.
    Always begin with `request-line`.

    ```
    request-line x-date content-type content-sha512 content-length
    ```

    This exact string becomes the `headers` parameter value in your
    `Authorization` header.
  </Step>

  <Step title="Build the signature string">
    The signature string is constructed by concatenating the values of each
    item in the header string, separated by newline characters `\n`. No
    trailing newline.

    For `request-line` — append the HTTP request line:

    ```
    POST /gateway/verify HTTP/1.1
    ```

    For each header — append `lowercased-header-name: value`:

    ```
    x-date: Fri, 17 Jan 2020 19:59:29 GMT
    content-type: application/json
    content-sha512: HpXfYk7qDatRNVlGHQOv3ELyAVd+JCdUcpHB5PMnu08EYbfH...
    content-length: 398
    ```

    Concatenated signature string:

    ```
    POST /gateway/verify HTTP/1.1\nx-date: Fri, 17 Jan 2020 19:59:29 GMT\ncontent-type: application/json\ncontent-sha512: HpXfYk7qDatRNVlGHQOv3ELyAVd+JCdUcpHB5PMnu08EYbfH...\ncontent-length: 398
    ```
  </Step>

  <Step title="Hash and encode the signature string">
    Sign the signature string using **HMAC-SHA512** with your secret key.
    Base64-encode the result.

    <Warning>
      Use **RAW** output from your HMAC library — not hex. Base64-encoding
      hex output will produce an incorrect signature.
    </Warning>

    The resulting value is your `signature` parameter:

    ```
    hAMqhSX6eogO1QpES9Dg9WynJWJPNxFLe1wtV4ppfvmGmqpYCiJYm6lqrHNjcmQUZCyMBdK86Zkm+m3BJwj3XA==
    ```
  </Step>

  <Step title="Assemble the Authorization header">
    Combine all parameters into the `Authorization` header:

    ```
    Authorization: hmac username="test", algorithm="hmac-sha512", headers="request-line x-date content-type content-sha512 content-length", signature="hAMqhSX6eogO1QpES9Dg9WynJWJPNxFLe1wtV4ppfvmGmqpYCiJYm6lqrHNjcmQUZCyMBdK86Zkm+m3BJwj3XA=="
    ```
  </Step>
</Steps>

***

## Full request example

```http theme={null}
POST /gateway/verify HTTP/1.1
Host: payapi-sandbox.ingo.money
Authorization: hmac username="test", algorithm="hmac-sha512", headers="request-line x-date content-type content-sha512 content-length", signature="hAMqhSX6eogO1QpES9Dg9WynJWJPNxFLe1wtV4ppfvmGmqpYCiJYm6lqrHNjcmQUZCyMBdK86Zkm+m3BJwj3XA=="
X-Date: Fri, 17 Jan 2020 19:59:29 GMT
Content-sha512: HpXfYk7qDatRNVlGHQOv3ELyAVd+JCdUcpHB5PMnu08EYbfHID7zQJXihCxjmGKRULH+QFYxYch05aDPKjWb+Q==
Content-Length: 398
Content-Type: application/json

{
  "participant_id": 00000,
  "account_type": "CA",
  "recipient_first_name": "Tom",
  "recipient_last_name": "Smith",
  "account": "4264531111111115",
  "expiration_date": "2212",
  "cvv": "000",
  "recipient_address1": "123 Main St.",
  "recipient_city": "Smallville",
  "recipient_state": "TX",
  "recipient_zip": "93245",
  "recipient_phone": "8015555555",
  "participant_unique_id1": "0001",
  "timestamp": 1579291169,
  "version": "11"
}
```

***

## Environments

| Product                            | Sandbox                                             | Production                                     |
| ---------------------------------- | --------------------------------------------------- | ---------------------------------------------- |
| IngoPay API                        | `https://payapi-sandbox.ingo.money`                 | `https://payapi.ingo.money`                    |
| Notify — Classic & Managed Parties | `https://payapi-sandbox.ingo.money`                 | `https://payapi.ingo.money`                    |
| Embedded Account Capture           | `https://iip-session-management-uat.ingo.money`     | `https://iip-session-management.ingo.money`    |
| Banking Platform                   | `https://api.sdev.banking.ingopayments.tech/api/v4` | `https://api.banking.ingopayments.tech/api/v4` |

Use sandbox credentials for all development and testing. Production credentials are issued after sandbox certification is complete.

***

## Common errors

| Error                    | Cause                               | Fix                                                                                     |
| ------------------------ | ----------------------------------- | --------------------------------------------------------------------------------------- |
| `401 Unauthorized`       | Invalid signature                   | Verify secret, signature string construction, and RAW (not hex) HMAC output             |
| `401 Clock skew`         | `X-Date` outside ±300s window       | Sync your server clock with NTP                                                         |
| `400 Body hash mismatch` | `Content-sha512` doesn't match body | Recompute hash from the exact body bytes being sent                                     |
| `400 Missing header`     | Required header absent              | Ensure `X-Date`, `Content-sha512`, `Content-Length`, and `Content-Type` are all present |

***

## Implementation notes

* The `secret` is never included in the request — only used locally to generate the signature
* Include `participant_id` in the request **body**, not in the headers
* Additional headers beyond the required set may be included and signed — add them to the header string in the order they appear
* The header string order in your `Authorization` header must exactly match the order used to build your signature string
