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

# Authentication

> Quick reference for HMAC authentication

export const GradientHoverCard = ({children, direction = "vertical", title, iconName, href}) => <a className="gradient-hover-card-wrapper" href={href}>
    <div className="gradient-hover-card-inner">
      <div className="gradient-hover-card-inner__vertical-container">
        <img className="gradient-hover-card-inner_icon" src={`/image/${iconName}.svg`} />
        <p className="gradient-hover-card-title">{title}</p>
        <p className="gradient-hover-card-content">{children}</p>
      </div>
    </div>
  </a>;

<Info>
  For complete implementation guides, code examples, and troubleshooting, see the [Authentication Guide](/fx/authentication) in Getting Started.
</Info>

## Overview

The HopNow API uses **HMAC-SHA256 signatures** to authenticate all requests. Every API request must include four authentication headers.

Client API requests use HMAC headers only. Do not use `Authorization: Bearer` for these endpoints.
The API playground can store `X-API-Key`, but `X-Timestamp`, `X-Nonce`, and `X-Signature` are request-specific and must be generated for each request.

## Required Headers

| Header        | Description                                          |
| ------------- | ---------------------------------------------------- |
| `X-API-Key`   | The `api_key` value returned when the key is created |
| `X-Signature` | HMAC-SHA256 signature of the request                 |
| `X-Timestamp` | Unix timestamp when request was created              |
| `X-Nonce`     | Unique random token (32 hex characters)              |

## Signature Format

Use the `secret` returned when the key is created as the HMAC-SHA256 signing key. The `api_key` value goes in `X-API-Key`.

The signature is created by hashing the following payload:

```
{METHOD}{PATH_AND_QUERY}{TIMESTAMP}{NONCE}{BODY}
```

**Components:**

* **METHOD**: Uppercase HTTP method (`GET`, `POST`, `PATCH`, `DELETE`)
* **PATH\_AND\_QUERY**: The URL path exactly as sent to HopNow, starting with `/`, followed by `?` and the query string when the request has query parameters. Do not include the scheme, host, port, or fragment.
* **TIMESTAMP**: Unix timestamp as string
* **NONCE**: Unique 32-character hex string (prevents replay attacks)
* **BODY**: Exact request body string sent over the wire (empty string for GET/DELETE)

For `https://api.hopnow.io/v1/customers/cus_123/accounts?size=1`, sign `/v1/customers/cus_123/accounts?size=1`.

## Quick Example

<CodeGroup>
  ```python Python theme={null}
  import hmac
  import hashlib
  import time
  import secrets

  def create_signature(method, path_and_query, timestamp, nonce, body, secret):
      payload = f"{method.upper()}{path_and_query}{timestamp}{nonce}{body}"
      signature = hmac.new(
          secret.encode('utf-8'),
          payload.encode('utf-8'),
          hashlib.sha256
      ).hexdigest()
      return signature

  # Usage
  timestamp = str(int(time.time()))
  nonce = secrets.token_hex(16)
  signature = create_signature(
      "POST",
      "/v1/customers/cus_123/accounts",
      timestamp,
      nonce,
      '{"name":"My Account"}',
      "your_secret"
  )
  ```

  ```javascript JavaScript theme={null}
  const crypto = require('crypto');

  function createSignature(method, pathAndQuery, timestamp, nonce, body, secret) {
      const payload = `${method.toUpperCase()}${pathAndQuery}${timestamp}${nonce}${body}`;
      return crypto
          .createHmac('sha256', secret)
          .update(payload)
          .digest('hex');
  }

  // Usage
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const nonce = crypto.randomBytes(16).toString('hex');
  const signature = createSignature(
      'POST',
      '/v1/customers/cus_123/accounts',
      timestamp,
      nonce,
      '{"name":"My Account"}',
      'your_secret'
  );
  ```
</CodeGroup>

## Security Requirements

* **Timestamp validation**: Requests older than 5 minutes are rejected
* **Nonce uniqueness**: Each nonce can only be used once within the 5-minute window
* **HTTPS only**: All requests must use HTTPS
* **Keep secrets secure**: Never expose your API secret in client-side code or logs

***

<CardGroup cols={1}>
  <GradientHoverCard iconName="full-authentication-guide" title="Full Authentication Guide" href="/fx/authentication">
    For complete implementation examples, how to get API keys, security best practices, error handling, and troubleshooting, see the comprehensive Authentication Guide.
  </GradientHoverCard>
</CardGroup>
