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

# Authentication

> Learn how to authenticate your API requests with TxnCheck

# Authentication

All API requests to TxnCheck must be authenticated using an API key. This page explains how to obtain and use your API keys, and optionally how to sign requests for enhanced security.

## Obtaining API Keys

<Info>
  API keys are provided by the TxnCheck team during merchant onboarding. Self-registration is not available.
</Info>

To obtain your API keys:

1. Contact your TxnCheck account manager
2. Or visit [TxnCheck Dashboard](https://app.txncheck.com)

Once your account is set up, you can view your API keys in the [Merchant Dashboard](https://dashboard.txncheck.in) under **Settings → API Keys**.

## API Key Authentication

Include your API key in the `X-API-Key` header with every request:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.txncheck.in/api/v1/upi-by-mobile" \
    -H "X-API-Key: fb_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{"mobile": "+919876543210"}'
  ```

  ```python Python theme={null}
  import requests

  headers = {
      "X-API-Key": "fb_your_api_key_here",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api.txncheck.in/api/v1/upi-by-mobile",
      headers=headers,
      json={"mobile": "+919876543210"}
  )
  ```

  ```javascript Node.js theme={null}
  const axios = require('axios');

  const response = await axios.post(
    'https://api.txncheck.in/api/v1/upi-by-mobile',
    { mobile: '+919876543210' },
    {
      headers: {
        'X-API-Key': 'fb_your_api_key_here',
        'Content-Type': 'application/json'
      }
    }
  );
  ```

  ```php PHP theme={null}
  <?php
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "https://api.txncheck.in/api/v1/upi-by-mobile");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "X-API-Key: fb_your_api_key_here",
      "Content-Type: application/json"
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
      "mobile" => "+919876543210"
  ]));

  $response = curl_exec($ch);
  curl_close($ch);
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "net/http"
  )

  func main() {
      payload := map[string]string{"mobile": "+919876543210"}
      body, _ := json.Marshal(payload)

      req, _ := http.NewRequest("POST", "https://api.txncheck.in/api/v1/upi-by-mobile", bytes.NewBuffer(body))
      req.Header.Set("X-API-Key", "fb_your_api_key_here")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, _ := client.Do(req)
      defer resp.Body.Close()
  }
  ```
</CodeGroup>

## Request Signing (Optional)

For enhanced security, you can sign your requests using HMAC-SHA256. When enabled for your merchant account, signed requests are required.

### Signature Headers

| Header        | Description                            |
| ------------- | -------------------------------------- |
| `X-API-Key`   | Your API key (always required)         |
| `X-Timestamp` | Current Unix timestamp in milliseconds |
| `X-Signature` | HMAC-SHA256 signature of the request   |

### Signature Algorithm

The signature is computed as:

```
signature = HMAC-SHA256(timestamp.METHOD.path.body, api_secret)
```

Where:

* `timestamp` - The value of `X-Timestamp` header
* `METHOD` - HTTP method in uppercase (e.g., `POST`)
* `path` - Full request path including query string (e.g., `/api/v1/upi-by-mobile`)
* `body` - JSON stringified request body (or `{}` if empty)
* `api_secret` - Your API secret key

### Signing Examples

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function signRequest(method, path, body, apiSecret) {
    const timestamp = Date.now().toString();
    const bodyString = JSON.stringify(body || {});
    const signaturePayload = `${timestamp}.${method}.${path}.${bodyString}`;
    
    const signature = crypto
      .createHmac('sha256', apiSecret)
      .update(signaturePayload)
      .digest('hex');
    
    return { timestamp, signature };
  }

  // Usage
  const { timestamp, signature } = signRequest(
    'POST',
    '/api/v1/upi-by-mobile',
    { mobile: '+919876543210' },
    'your_api_secret_here'
  );

  const response = await axios.post(
    'https://api.txncheck.in/api/v1/upi-by-mobile',
    { mobile: '+919876543210' },
    {
      headers: {
        'X-API-Key': 'fb_your_api_key_here',
        'X-Timestamp': timestamp,
        'X-Signature': signature,
        'Content-Type': 'application/json'
      }
    }
  );
  ```

  ```python Python theme={null}
  import hmac
  import hashlib
  import time
  import json
  import requests

  def sign_request(method, path, body, api_secret):
      timestamp = str(int(time.time() * 1000))
      body_string = json.dumps(body or {}, separators=(',', ':'))
      signature_payload = f"{timestamp}.{method}.{path}.{body_string}"
      
      signature = hmac.new(
          api_secret.encode(),
          signature_payload.encode(),
          hashlib.sha256
      ).hexdigest()
      
      return timestamp, signature

  # Usage
  body = {"mobile": "+919876543210"}
  timestamp, signature = sign_request(
      "POST",
      "/api/v1/upi-by-mobile",
      body,
      "your_api_secret_here"
  )

  response = requests.post(
      "https://api.txncheck.in/api/v1/upi-by-mobile",
      headers={
          "X-API-Key": "fb_your_api_key_here",
          "X-Timestamp": timestamp,
          "X-Signature": signature,
          "Content-Type": "application/json"
      },
      json=body
  )
  ```

  ```php PHP theme={null}
  <?php
  function signRequest($method, $path, $body, $apiSecret) {
      $timestamp = (string)(time() * 1000);
      $bodyString = json_encode($body ?: new stdClass());
      $signaturePayload = "{$timestamp}.{$method}.{$path}.{$bodyString}";
      
      $signature = hash_hmac('sha256', $signaturePayload, $apiSecret);
      
      return [$timestamp, $signature];
  }

  // Usage
  $body = ["mobile" => "+919876543210"];
  list($timestamp, $signature) = signRequest(
      "POST",
      "/api/v1/upi-by-mobile",
      $body,
      "your_api_secret_here"
  );

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "https://api.txncheck.in/api/v1/upi-by-mobile");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "X-API-Key: fb_your_api_key_here",
      "X-Timestamp: " . $timestamp,
      "X-Signature: " . $signature,
      "Content-Type: application/json"
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));

  $response = curl_exec($ch);
  curl_close($ch);
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "crypto/hmac"
      "crypto/sha256"
      "encoding/hex"
      "encoding/json"
      "fmt"
      "net/http"
      "time"
  )

  func signRequest(method, path string, body map[string]string, apiSecret string) (string, string) {
      timestamp := fmt.Sprintf("%d", time.Now().UnixMilli())
      bodyBytes, _ := json.Marshal(body)
      signaturePayload := fmt.Sprintf("%s.%s.%s.%s", timestamp, method, path, string(bodyBytes))

      mac := hmac.New(sha256.New, []byte(apiSecret))
      mac.Write([]byte(signaturePayload))
      signature := hex.EncodeToString(mac.Sum(nil))

      return timestamp, signature
  }

  func main() {
      body := map[string]string{"mobile": "+919876543210"}
      timestamp, signature := signRequest("POST", "/api/v1/upi-by-mobile", body, "your_api_secret_here")

      bodyBytes, _ := json.Marshal(body)
      req, _ := http.NewRequest("POST", "https://api.txncheck.in/api/v1/upi-by-mobile", bytes.NewBuffer(bodyBytes))
      req.Header.Set("X-API-Key", "fb_your_api_key_here")
      req.Header.Set("X-Timestamp", timestamp)
      req.Header.Set("X-Signature", signature)
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, _ := client.Do(req)
      defer resp.Body.Close()
  }
  ```
</CodeGroup>

### Timestamp Validation

<Warning>
  Signed requests must include a timestamp within **5 minutes** of the current server time. Requests with expired timestamps will be rejected with a `401 Unauthorized` error.
</Warning>

## Method Access Control

Your API key may be configured with access to specific verification methods. If you attempt to use a method not enabled for your account, you'll receive a `403 Forbidden` error.

Contact your account manager to request access to additional methods.

## IP Whitelisting

For enhanced security, you can configure IP whitelisting for your merchant account. When enabled, API requests will only be accepted from your whitelisted IP addresses.

<Info>
  IP whitelisting is configured in the Merchant Dashboard under **Settings → Security**.
</Info>

## Error Responses

Authentication errors return standard HTTP status codes:

| Status Code        | Description                              |
| ------------------ | ---------------------------------------- |
| `401 Unauthorized` | Missing or invalid API key               |
| `401 Unauthorized` | Invalid or expired signature             |
| `403 Forbidden`    | API key lacks access to requested method |
| `403 Forbidden`    | Request from non-whitelisted IP          |

```json Example Error Response theme={null}
{
  "statusCode": 401,
  "message": "Invalid API key",
  "error": "Unauthorized"
}
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Use Environment Variables" icon="lock">
    Store API keys in environment variables, never in code
  </Card>

  <Card title="Enable Request Signing" icon="shield">
    Use HMAC signatures for production integrations
  </Card>

  <Card title="Use IP Whitelisting" icon="network-wired">
    Restrict API access to known IP addresses
  </Card>

  <Card title="Monitor API Usage" icon="chart-line">
    Track usage in the dashboard for anomalies
  </Card>
</CardGroup>
