Fintech APIs & Platform for KYC, Verification & Transactions in India | Eko Platform Services
Eko Platform Services Logo

How Authentication Works

Every Eko API request is authenticated with a static key plus a per-request HMAC signature. Nothing secret ever travels on the wire in plain form.

The two keys

KeyWhere it comes fromHow it's used
Access Key (also called Auth Key)Shared once, kept server-side only. Get UAT key from your dashboard; production key after KYCNever sent in a request; used to compute the secret-key
Developer KeyGet UAT key from your dashboard; production key after KYCSent as the developer_key header

Request headers

HeaderRequiredDescription
developer_keyyesYour static developer key.
secret-keyyesPer-request HMAC signature (see below).
secret-key-timestampyesCurrent time in milliseconds since the UNIX epoch.
content-typeyesapplication/json

Computing the secret-key

The signature binds the request to a timestamp, so it must be generated fresh for every call:

  1. Base64-encode the access_key — keep this as a string.
  2. Take the current timestamp in milliseconds, as a string.
  3. Compute HMAC-SHA256 with the timestamp as the message and that base64 string as the key.
  4. Base64-encode the result — that's the secret-key.

Send the same timestamp in secret-key-timestamp. A stale or mismatched timestamp returns 403 Forbidden.

secret-key = base64( HMAC-SHA256( message = timestamp, key = base64(access_key) ) )

Common mistake: the HMAC key is the base64 string base64(access_key), used as-is. Do not base64-decode it back to raw bytes before signing — that produces a different signature and a 403.

Code examples

Sign on your backend — the access_key must never reach a browser. The same recipe in five languages:

// Backend only. Never expose access_key in a browser.
import crypto from "node:crypto";
const accessKey = process.env.EKO_ACCESS_KEY;
const timestamp = Date.now().toString();
const encodedKey = Buffer.from(accessKey).toString("base64");
const secretKey = crypto
.createHmac("sha256", encodedKey)
.update(timestamp)
.digest("base64");
// headers: { developer_key, "secret-key": secretKey, "secret-key-timestamp": timestamp }

Try it: secret-key playground

Paste an access key and a timestamp to see the exact secret-key those inputs produce — or paste a signature your own code generated and check it against ours to find out why a request is coming back 403.

secret-key playground
base64( HMAC-SHA256( timestamp, base64(access_key) ) )
Runs in your browser

Send this exact value as secret-key-timestamp.

secret-key
Enter an access key and timestamp
secret-key-timestamp
Waiting for a valid timestamp
Verify an existing signature

Paste a signature above to compare it against the one computed from the same access key and timestamp.

Warning

This playground signs entirely inside your browser with the Web Crypto API — your access key is never sent to Eko or stored anywhere. That is safe for a scratchpad, but not a pattern to copy: in a real integration the access_key must stay on your backend, because anything shipped to a browser is public.