Skip to main content

POST /v1/payment-links

Create a payment link. Returns a shareable URL and a unique address per enabled crypto rail. The customer opens the link, picks how they want to pay (M-Pesa, TRON, BSC), and pays โ€” your webhook fires on confirmation.

Environment is inherited from your API key

Pass an hm_test_* key โ†’ test link (sandbox STK push, simulated on-chain). Pass an hm_live_* key โ†’ live link (real M-Pesa charges, real on-chain). Never pass an environment field โ€” HelaMesh infers it from the key.

Headersโ€‹

x-api-key: hm_test_โ€ฆ # or hm_live_โ€ฆ
content-type: application/json

Bodyโ€‹

FieldTypeRequiredNotes
usdtAmountstringyes*Decimal USDT amount, e.g. "25.00". Required if not M-Pesa only.
mpesaAmountnumbernoKES amount. If omitted and MPESA rail is enabled, HelaMesh converts from usdtAmount using the live rate.
enabledRailsstring[]yesOne or more of "MPESA", "USDT_TRON", "USDT_BSC"
descriptionstringnoShown to the customer on the checkout page
merchantRefstringnoYour own reference ID โ€” returned in webhooks
metadataobjectnoFree-form JSON, returned in webhooks unchanged
expiresInMinutesnumbernoLink TTL. Defaults to 1440 (24 hours).

Exampleโ€‹

node.js
const res = await fetch('https://api.helamesh.com/v1/payment-links', {
method: 'POST',
headers: {
'x-api-key': process.env.HELAMESH_API_KEY,
'content-type': 'application/json',
},
body: JSON.stringify({
usdtAmount: '100',
enabledRails: ['MPESA', 'USDT_TRON', 'USDT_BSC'],
description: 'Order #1042 โ€” Web design deposit',
merchantRef: 'order_1042',
metadata: { customerId: 'cus_abc123' },
}),
});

const link = await res.json();
// Send link.checkoutUrl to your customer
console.log('Pay here:', link.checkoutUrl);

Responseโ€‹

201 Created
{
"id": "6a20334a21638503775afa39",
"status": "PENDING",
"environment": "test",
"usdtAmount": "100",
"mpesaAmount": 13421,
"enabledRails": ["MPESA", "USDT_TRON", "USDT_BSC"],
"tronAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"bscAddress": "0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db",
"mpesaShortcode": "174379",
"description": "Order #1042 โ€” Web design deposit",
"merchantRef": "order_1042",
"metadata": { "customerId": "cus_abc123" },
"expiresAt": "2026-06-04T12:00:00.000Z",
"createdAt": "2026-06-03T12:00:00.000Z",
"checkoutUrl": "https://pay.helamesh.com/p/6a20334a21638503775afa39"
}

Response fieldsโ€‹

FieldTypeNotes
idstringPayment link ID โ€” store this on your order
statusstringPENDING | PROCESSING | CONFIRMED | EXPIRED | CANCELLED
environmentstring"test" or "live"
usdtAmountstringNormalised USDT decimal string
mpesaAmountnumber | nullKES amount shown to customer. Null if M-Pesa rail not enabled.
enabledRailsstring[]Rails available on this link
tronAddressstring | nullUnique TRC20 receiving address for this link. Null if USDT_TRON not enabled.
bscAddressstring | nullUnique BEP20 receiving address for this link. Null if USDT_BSC not enabled.
mpesaShortcodestring | nullConnected M-Pesa paybill number. Null if MPESA not enabled.
descriptionstring | nullDescription shown on checkout
merchantRefstring | nullYour reference, echoed in webhooks
metadataobject | nullYour metadata, echoed in webhooks
expiresAtISO8601When the link expires
checkoutUrlstringThe URL to send your customer

Fetch a single payment link by ID. Requires your secret API key.

curl https://api.helamesh.com/v1/payment-links/6a20334a21638503775afa39 \
-H "x-api-key: hm_test_..."

Response shape is identical to the create response above, plus confirmedRail, confirmedAt, externalId, and payer fields which populate on confirmation:

FieldTypeNotes
confirmedRailstring | nullWhich rail the customer paid with: "MPESA", "USDT_TRON", or "USDT_BSC"
confirmedAtISO8601 | nullWhen payment was confirmed
externalIdstring | nullM-Pesa receipt code or on-chain tx hash
payerstring | nullM-Pesa phone number or on-chain sender address

List all payment links for your store. Requires your secret API key.

curl "https://api.helamesh.com/v1/payment-links?status=PENDING&limit=20" \
-H "x-api-key: hm_test_..."

Query paramsโ€‹

ParamDefaultNotes
statusโ€”Filter by status
limit20Max results per page (1โ€“100)
page1Page number