User Login
POST/v1/users/login
Using email let us create access token which can be utilised for subsequent api request, without this, request will be denied with reason as unauthorised.
Signed Requests (Trusted Issuance)
This endpoint requires your account's calling IP to be whitelisted, and a signed x-timestamp / x-signature header pair proving the request genuinely originates from your backend (not just anyone holding a leaked x-api-key). Both are mandatory on every request.
| Header | Description |
|---|---|
x-timestamp | Current Unix timestamp (seconds). Must be within 5 minutes of server time. |
x-signature | hex(HMAC-SHA256(apiSecret, apiKey + ":" + timestamp)), computed with your Client Secret. |
Your calling IP must be whitelisted on your merchant account, or every request to this endpoint is rejected with 403 Forbidden. Contact tech team or support@onmeta.in to whitelist the IP's.
x-timestamp and x-signature are required on every request. If either header is missing, incomplete, stale, or doesn't match, the request is rejected with 401 Unauthorized.
Code for generating x-timestamp / x-signature
- JavaScript
- Python
- Java
- PHP
- Go
const crypto = require("crypto");
function signTrustedIssuance(apiKey, apiSecret, timestamp) {
const payload = `${apiKey}:${timestamp}`;
return crypto.createHmac("sha256", apiSecret).update(payload).digest("hex");
}
const apiKey = "<CLIENT_ID>";
const apiSecret = "<CLIENT_SECRET>";
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = signTrustedIssuance(apiKey, apiSecret, timestamp);
console.log({ timestamp, signature });
import hmac
import hashlib
import time
def sign_trusted_issuance(api_key, api_secret, timestamp):
payload = f"{api_key}:{timestamp}"
return hmac.new(api_secret.encode(), payload.encode(), hashlib.sha256).hexdigest()
api_key = "<CLIENT_ID>"
api_secret = "<CLIENT_SECRET>"
timestamp = str(int(time.time()))
signature = sign_trusted_issuance(api_key, api_secret, timestamp)
print(timestamp, signature)
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class TrustedIssuance {
public static String sign(String apiKey, String apiSecret, String timestamp) throws Exception {
String payload = apiKey + ":" + timestamp;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiSecret.getBytes("UTF-8"), "HmacSHA256"));
byte[] hash = mac.doFinal(payload.getBytes("UTF-8"));
StringBuilder result = new StringBuilder();
for (byte b : hash) {
result.append(String.format("%02x", b));
}
return result.toString();
}
public static void main(String[] args) throws Exception {
String apiKey = "<CLIENT_ID>";
String apiSecret = "<CLIENT_SECRET>";
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String signature = sign(apiKey, apiSecret, timestamp);
System.out.println(timestamp + " " + signature);
}
}
<?php
function signTrustedIssuance($apiKey, $apiSecret, $timestamp) {
$payload = $apiKey . ':' . $timestamp;
return hash_hmac('sha256', $payload, $apiSecret);
}
$apiKey = '<CLIENT_ID>';
$apiSecret = '<CLIENT_SECRET>';
$timestamp = (string) time();
$signature = signTrustedIssuance($apiKey, $apiSecret, $timestamp);
echo $timestamp . ' ' . $signature;
?>
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"time"
)
func signTrustedIssuance(apiKey, apiSecret, timestamp string) string {
mac := hmac.New(sha256.New, []byte(apiSecret))
mac.Write([]byte(apiKey + ":" + timestamp))
return hex.EncodeToString(mac.Sum(nil))
}
func main() {
apiKey := "<CLIENT_ID>"
apiSecret := "<CLIENT_SECRET>"
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
signature := signTrustedIssuance(apiKey, apiSecret, timestamp)
fmt.Println(timestamp, signature)
}
Log in to your Merchant Dashboard → Setup → API's Setup. Use the Client Secret (not the Client ID) as apiSecret. Keep this value private and never expose it in client-side code or public repositories.
Access tokens expire after 15 minutes.
JWT Claims
The accessToken returned is a signed JWT. Its payload contains the following claims:
| Claim | Type | Description |
|---|---|---|
sub | String | Unique user identifier (ULID) |
aud | String | Your application's Client ID — unique per API key |
iss | String | Token issuer (https://iam.onmeta.io/onmeta) |
iat | Integer | Issued-at time (Unix timestamp) |
exp | Integer | Expiration time (Unix timestamp) — 15 minutes after iat |
jti | String | Unique JWT identifier (UUID/ULID) — used for request tracing and replay prevention |
tenant_id | String | Internal Onmeta tenant identifier |
Request
Responses
- 200
- 400
- 401
- 403
Returns access and refresh tokens for the authenticated user.
Invalid or missing email address.
Unauthorized — one of several failures:
- Missing or incorrect
x-api-keyheader. x-timestamp/x-signaturemissing, incomplete, stale (older than 5 minutes), or not matching the expected signature — both are required on every request. See "Signed Requests (Trusted Issuance)" below.
Forbidden — one of:
- IP whitelisting is not configured for this merchant. Contact tech team or support@onmeta.in to whitelist the IP's.
- The calling IP is not in the configured whitelist.