Transaction status
Recover one merchant-owned transaction using its returned identifier.
Retrieve a transaction
External transaction status is the HMAC route for a single merchant-owned ledger transaction. Resolve transaction_id before signing its path.
Keep your references
The example includes internal_ref, external_ref, gateway_ref, gross/fees/net amounts, currency, category, method, status, payee information and timestamps. Amounts appear as decimal strings; do not silently treat every money field in the platform as an integer in paise.
Reconcile asynchronous updates
Callbacks are the primary update channel. Use status GET when a callback is delayed, missed or needs investigation. Payout-specific status uses the payout route; dashboard transaction listing is not a public merchant listing API.
Avoid assumed state machines
Different endpoints use paid, SUCCESS, completed, COMPLETED and processing in examples. The complete vocabulary, transitions and terminal-state guarantees require backend confirmation.
Request example
Choose Node.js, Python, PHP, Ruby, Java or cURL. Run signed requests on your backend. PHP, Ruby and Java include signing directly. Java requires JDK 17 or newer.
Signing helpers: Node.js · Python. cURL shows the request shape; generate its signature first.
import { signedHeaders } from './signing.mjs';
const transaction_id = process.env.ZYTEPE_TRANSACTION_ID;
if (!transaction_id) throw new Error('Set ZYTEPE_TRANSACTION_ID to the returned identifier');
const path = `/api/v1/transactions/external/status/${encodeURIComponent(transaction_id)}`;
const query = '';
const body = ''; // GET requests have no body
const headers = signedHeaders({
method: 'GET', path, query, body,
keyId: process.env.ZYTEPE_API_KEY_ID,
secret: process.env.ZYTEPE_API_SECRET,
});
const url = 'https://api.zytepe.com' + path + (query ? '?' + query : '');
const response = await fetch(url, { method: 'GET', headers });
if (!response.ok) throw new Error('Request failed: HTTP ' + response.status);
const result = await response.json();
// Store the returned identifiers securely. Do not log customer data.import json, os
from urllib.parse import quote
from urllib.request import Request, urlopen
from zytepe_signing import signed_headers
transaction_id = os.environ['ZYTEPE_TRANSACTION_ID']
path = f'/api/v1/transactions/external/status/{quote(transaction_id, safe="")}'
query = ''
body = '' # GET requests have no body
headers = signed_headers(
method='GET', path=path, query=query, body=body,
key_id=os.environ['ZYTEPE_API_KEY_ID'],
secret=os.environ['ZYTEPE_API_SECRET'],
)
url = 'https://api.zytepe.com' + path + ('?' + query if query else '')
request = Request(url, method='GET', headers=headers)
with urlopen(request, timeout=30) as response:
result = json.load(response)
# Store identifiers securely; handle HTTPError/URLError in your application.<?php
// PHP 8+ with the cURL extension. Run on your server.
function envRequired(string $name): string {
$value = getenv($name);
if ($value === false || $value === '') throw new RuntimeException('Set ' . $name);
return $value;
}
$path = '/api/v1/transactions/external/status/{transaction_id}';
$path = str_replace('{transaction_id}', rawurlencode(envRequired('ZYTEPE_TRANSACTION_ID')), $path);
$query = '';
$body = ''; // No body for GET
$headers = [];
$key = envRequired('ZYTEPE_API_KEY_ID');
$secret = envRequired('ZYTEPE_API_SECRET');
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(16));
$canonical = implode("\n", ['GET', $path, $query, $timestamp, $nonce, hash('sha256', $body)]);
$signature = hash_hmac('sha256', $canonical, $secret);
$headers = ["X-API-KEY-ID: $key", "X-API-TIMESTAMP: $timestamp", "X-API-NONCE: $nonce", "X-API-SIGNATURE: $signature"];
$url = 'https://api.zytepe.com' . $path . ($query !== '' ? '?' . $query : '');
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 30]);
$response = curl_exec($ch);
if ($response === false) throw new RuntimeException(curl_error($ch));
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) throw new RuntimeException('HTTP ' . $status);
$result = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
// Store returned identifiers securely. Recover uncertain payments before retrying.require 'net/http'
require 'uri'
require 'json'
require 'openssl'
require 'securerandom'
path = '/api/v1/transactions/external/status/{transaction_id}'
path = path.gsub('{transaction_id}', URI.encode_www_form_component(ENV.fetch('ZYTEPE_TRANSACTION_ID')).gsub('+', '%20'))
query = ''
body = '' # No body for GET
headers = {}
key = ENV.fetch('ZYTEPE_API_KEY_ID')
secret = ENV.fetch('ZYTEPE_API_SECRET')
timestamp = Time.now.to_i.to_s
nonce = SecureRandom.hex(16)
canonical = ['GET', path, query, timestamp, nonce, OpenSSL::Digest::SHA256.hexdigest(body)].join("\n")
signature = OpenSSL::HMAC.hexdigest('SHA256', secret, canonical)
headers = { 'X-API-KEY-ID' => key, 'X-API-TIMESTAMP' => timestamp,
'X-API-NONCE' => nonce, 'X-API-SIGNATURE' => signature }
uri = URI('https://api.zytepe.com' + path + (query.empty? ? '' : '?' + query))
request = Net::HTTP::Get.new(uri, headers)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, open_timeout: 10, read_timeout: 30) do |http|
http.request(request)
end
raise 'HTTP ' + response.code unless response.is_a?(Net::HTTPSuccess)
result = JSON.parse(response.body)
# Store returned identifiers securely. Recover uncertain payments before retrying.// Java 17+. Save as ZytePeExample.java and run on your server.
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.security.MessageDigest;
import java.util.HexFormat;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class ZytePeExample {
private static String env(String name) {
String value = System.getenv(name);
if (value == null || value.isBlank()) throw new IllegalArgumentException("Set " + name);
return value;
}
public static void main(String[] args) throws Exception {
String path = "/api/v1/transactions/external/status/{transaction_id}";
path = path.replace("{transaction_id}", URLEncoder.encode(env("ZYTEPE_TRANSACTION_ID"), StandardCharsets.UTF_8).replace("+", "%20"));
String query = "";
String body = ""; // GET requests have no body
var request = HttpRequest.newBuilder(URI.create(
"https://api.zytepe.com" + path + (query.isEmpty() ? "" : "?" + query)))
.timeout(Duration.ofSeconds(30));
String key = env("ZYTEPE_API_KEY_ID");
String secret = env("ZYTEPE_API_SECRET");
String timestamp = Long.toString(Instant.now().getEpochSecond());
String nonce = UUID.randomUUID().toString().replace("-", "");
String bodyHash = HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256")
.digest(body.getBytes(StandardCharsets.UTF_8)));
String canonical = String.join("\n", "GET", path, query, timestamp, nonce, bodyHash);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String signature = HexFormat.of().formatHex(mac.doFinal(canonical.getBytes(StandardCharsets.UTF_8)));
request.header("X-API-KEY-ID", key).header("X-API-TIMESTAMP", timestamp)
.header("X-API-NONCE", nonce).header("X-API-SIGNATURE", signature);
request.method("GET", HttpRequest.BodyPublishers.noBody());
var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
var response = client.send(request.build(), HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
if (response.statusCode() < 200 || response.statusCode() >= 300)
throw new IllegalStateException("HTTP " + response.statusCode());
String result = response.body(); // Parse JSON using your application's JSON library.
// Store identifiers securely. Recover uncertain payments before retrying.
}
}curl --request GET \
--url 'https://api.zytepe.com/api/v1/transactions/external/status/{transaction_id}' \
--header 'X-API-KEY-ID: <key-id>' \
--header 'X-API-TIMESTAMP: <unix-seconds>' \
--header 'X-API-NONCE: <fresh-nonce>' \
--header 'X-API-SIGNATURE: <signature>'Path, query and headers
transaction_idRequiredpathUse the identifier returned by the corresponding creation operation.
Request body
No request body for GET.
Example response
{
"success": true,
"message": "Transaction status retrieved from ZytePe ledger.",
"data": {
"id": "ca9a58aa-d578-4fc2-a9f4-fb8d090d4b5f",
"internal_ref": "ZY-INT-2042-AX19",
"external_ref": "PAYOUT-2026-00041",
"gateway_ref": "BANKREF98344210",
"amount_gross": "1500.0000",
"amount_fees": "15.0000",
"amount_net": "1485.0000",
"currency": "INR",
"category": "DISBURSEMENT",
"method": "IMPS",
"status": "COMPLETED",
"payee_id": "d965aa45-1952-4749-aa52-2bed21470ffd",
"payee_name": "Aditi Traders",
"failure_reason": null,
"created_at": "2026-05-03T10:42:10.110Z",
"updated_at": "2026-05-03T10:43:18.240Z"
}
}