Hands In
Authentication

API Authentication

Learn how API authentication works with Hands In

Get Markdown

Overview

Hands In authenticates all API requests using merchant API keys. Each merchant account is issued a unique API key via the Hands In dashboard, and this key must be included in every request.

Think of your API key as a secret identifier for your integration — similar to a password. Keep it secure and never expose it publicly.

Using the x-api-key Header

To authenticate a request, include your API key in a x-api-key HTTP header field.

For example, if your API key is abcd1234, your request headers would include it like so:

POST /v1/multi-card-payments HTTP/1.1
Host: api.sandbox.handsin.com
Content-Type: application/json
Accept: application/json
x-api-key: abcd1234

See examples below

curl --request POST \
  --url https://api.sandbox.handsin.com/v1/multi-card-payments \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "x-api-key: <your-api-key>" \
  --data '{
    "amountMoney": {
      "currency": "GBP",
      "amount": 50000
    },
    "idempotencyKey": "<unique-random-string>"
  }'
const url = "https://api.sandbox.handsin.com/v1/multi-card-payments";

const payload = {
  amountMoney: {
    currency: "GBP",
    amount: 50000
  },
  idempotencyKey: "<unique-random-string>"
};

try {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/json",
      "x-api-key": "<your-api-key>"
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    throw new Error(`Response status: ${response.status}`);
  }

  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error("Request failed:", error.message);
}
import requests

url = "https://api.sandbox.handsin.com/v1/multi-card-payments"
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "x-api-key": "<your-api-key>"
}
payload = {
    "amountMoney": {
        "currency": "GBP",
        "amount": 50000
    },
    "idempotencyKey": "<unique-random-string>"
}

try:
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    print(response.json())
except requests.exceptions.RequestException as e:
    print(f"Request failed: {e}")
$headers = @{
  "Accept" = "application/json"
  "Content-Type" = "application/json"
  "x-api-key" = "<your-api-key>"
}

$body = @{
  amountMoney = @{
    currency = "GBP"
    amount = 50000
  }
  idempotencyKey = "<unique-random-string>"
} | ConvertTo-Json -Depth 3

try {
$response = Invoke-RestMethod -Uri "https://api.sandbox.handsin.com/v1/multi-card-payments"
-Method POST -Headers $headers -Body $body
$response
} catch {
Write-Host "Request failed: $($_.Exception.Message)"
}

The Hands In platform checks this header on every request and only allows access if the key is valid. You can find your API key in the Hands In merchant dashboard.

👉 Refer to the API Keys for instructions on obtaining and managing your keys.

Sandbox and Live Environments

Hands In provides two separate environments whilst integrating - testing (Sandbox) and production (Live).

EnvironmentBase URLReal TransactionsPurpose
Sandboxhttps://api.sandbox.handsin.com/v1❌ NoUsed for testing and development. No real payments are processed.
Livehttps://api.handsin.com/v1✅ YesUsed in production. All requests are processed as live transactions.

Key Differences

  • Authentication: Each environment uses different API keys. Use your Sandbox key for sandbox URLs and your Live key for live URLs

  • Webhooks: You'll need to configure webhooks separately for each environment via Developers > Webhooks.

  • No Real Charges in Sandbox: The Sandbox API simulates payment flows, and no live transactions are made.

  • Same API Structure: Both environments use the same endpoints, request formats, and response structures — making it easy to move from testing to production.


❌ Authentication Errors

If a request is made without a valid API key, the API will return one of the following errors:

Status CodeMeaning
401 UnauthorizedNo valid API key was provided. The server received no valid credentials.
403 ForbiddenThe API key was provided but is not authorized to access or perform an action on the resource (e.g., wrong environment, invalid permissions or revoked key).

✅ Troubleshooting Checklist

  • Are you using the correct API key for the environment?
  • Are you correctly setting the x-api-key header in your request?

On this page