Create Payment Link
Creates a collection intent and returns the checkout URL/slug for customer payment.
/api/v1/collections/intents/apiMerchant HMACAuthentication
Use merchant HMAC headers and sign the exact path, query and raw body.
See authentication.
Workflow notes
- Use notify_url when a single link needs its own callback destination. The merchant profile notify URLs remain the account-level defaults.
- The returned short_id is the slug used by the checkout flow and the public link-status endpoint.
Observed test condition: This specific merchant received HTTP 400 with
CCAvenue PSP MID is not assigned to this merchant.despite passing authentication. PSP mapping/merchant enablement must be verified; do not imply a sandbox exists. The sample request setsmax_limitbut the sample response hasmax_limit: null; confirm actual field semantics before writing parameter rules.
Before you send
Check the field labels and use your enabled merchant account. Examples illustrate the API contract; confirm deployment-specific limits and error handling before launch. This page never sends a request.
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 path = `/api/v1/collections/intents/api`;
const query = '';
const payload = {
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
};
const body = JSON.stringify(payload);
const headers = signedHeaders({
method: 'POST', path, query, body,
keyId: process.env.ZYTEPE_API_KEY_ID,
secret: process.env.ZYTEPE_API_SECRET,
});
headers['Content-Type'] = 'application/json';
const url = 'https://api.zytepe.com' + path + (query ? '?' + query : '');
const response = await fetch(url, { method: 'POST', headers, body });
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
path = f'/api/v1/collections/intents/api'
query = ''
payload = json.loads('''{
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
}''')
body = json.dumps(payload, separators=(',', ':'), ensure_ascii=False)
headers = signed_headers(
method='POST', path=path, query=query, body=body,
key_id=os.environ['ZYTEPE_API_KEY_ID'],
secret=os.environ['ZYTEPE_API_SECRET'],
)
headers['Content-Type'] = 'application/json'
url = 'https://api.zytepe.com' + path + ('?' + query if query else '')
request = Request(url, method='POST', headers=headers, data=body.encode('utf-8'))
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/collections/intents/api';
$query = '';
$body = <<<'JSON'
{
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
}
JSON;
$headers = [];
$key = envRequired('ZYTEPE_API_KEY_ID');
$secret = envRequired('ZYTEPE_API_SECRET');
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(16));
$canonical = implode("\n", ['POST', $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"];
$headers[] = 'Content-Type: application/json';
$url = 'https://api.zytepe.com' . $path . ($query !== '' ? '?' . $query : '');
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 30, CURLOPT_POSTFIELDS => $body]);
$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/collections/intents/api'
query = ''
body = <<~'JSON'.chomp
{
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
}
JSON
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 = ['POST', 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 }
headers['Content-Type'] = 'application/json'
uri = URI('https://api.zytepe.com' + path + (query.empty? ? '' : '?' + query))
request = Net::HTTP::Post.new(uri, headers)
request.body = body
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/collections/intents/api";
String query = "";
String body = """
{
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
}
""".stripTrailing();
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", "POST", 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.header("Content-Type", "application/json");
request.method("POST", HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8));
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 POST \
--url 'https://api.zytepe.com/api/v1/collections/intents/api' \
--header 'X-API-KEY-ID: <key-id>' \
--header 'X-API-TIMESTAMP: <unix-seconds>' \
--header 'X-API-NONCE: <fresh-nonce>' \
--header 'X-API-SIGNATURE: <signature>' \
--header 'Content-Type: application/json' \
--data-binary @request.jsonRequest fields
Optional fields can be omitted. Conditional fields depend on the payment method. Labels reflect the reviewed API schemas and handler checks.
titleRequiredCheckout title.
amountRequiredPayment amount in the documented currency.
external_idRequiredYour order or invoice reference; required by the API checkout handler.
customer_contextRequiredCustomer identity; required by the API checkout handler.
customer_context.full_nameRequiredRequired customer detail.
customer_context.email_addressRequiredRequired customer detail.
customer_context.phone_numberRequiredRequired customer detail.
descriptionOptionalAdditional checkout description.
usage_limitOptionalDefaults to 1.
min_limitOptionalDefaults to 1.0000.
max_limitOptionalUpper amount limit; source examples do not establish its effect on a fixed-amount checkout.
currencyOptionalDefaults to INR.
expiry_daysOptionalDefaults to 7 days.
customer_context.dial_codeOptionalDefaults to +91.
notify_urlOptionalLink-specific callback destination.
tagsOptionalAdditional business context.
Request body
{
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"usage_limit": 1,
"amount": 2500,
"min_limit": 1,
"max_limit": 50000,
"currency": "INR",
"expiry_days": 7,
"external_id": "INV-2042",
"notify_url": "https://merchant.example.com/hooks/collection-link",
"customer_context": {
"full_name": "Rahul Sharma",
"email_address": "rahul@example.com",
"phone_number": "9876543210",
"dial_code": "+91"
},
"tags": {
"source": "merchant-api",
"channel": "web"
}
}Example response
{
"success": true,
"message": "Payment link created via API.",
"data": {
"id": "49c2ebf2-f651-473e-ab78-6c154665df92",
"short_id": "s0oJRkuT6OY",
"title": "Invoice INV-2042",
"description": "April subscription renewal",
"fixed_amount": "2500.0000",
"min_limit": "1.0000",
"max_limit": null,
"currency": "INR",
"usage_limit": 1,
"current_usage_count": 0,
"status": "active",
"is_active": true,
"expires_at": "2026-05-10T10:30:00Z",
"checkout_url": "https://pay.zytepe.com/s0oJRkuT6OY"
}
}