Create Payment Link API

Create a Herepay payment link programmatically and get back a public pay_url that you redirect your customer to. The pay page is the same dynamic checkout a dashboard‑created link uses (FPX bank selection → payment → receipt), so no UI work is needed on the integrator side — just create the link and redirect.

Ready-to-use file

Herepay Create Payment Link API.md
Download .md

Endpoint

POST /api/integration/create-payment-link
EnvironmentBase URL
UAThttps://uat.herepay.org
Productionhttps://app.herepay.org

Full URL (UAT): https://uat.herepay.org/api/integration/create-payment-link


Authentication

Authenticate with your team's Secret Key, sent as a request header. This is the same SecretKey used by the other /api/integration/* endpoints.

SecretKey: <your-team-secret-key>

A missing or wrong key returns 401 Unauthorized.

Find your Secret Key in the Herepay dashboard under your team's API/Integration settings. Treat it as a credential — never expose it in client‑side code.


Request

Headers

HeaderValueRequired
SecretKeyYour team secret key
Content-Typeapplication/json
Acceptapplication/json

Body parameters

Only title and amount are required. Everything else is optional and has a sensible default.

FieldTypeRequiredDefaultDescription
titlestring (≤255)Name of what's being paid for. Shown on the pay page.
amountnumberAmount in MYR. Range 199,999,999. Two decimals.
descriptionstring (≤65000)nullHTML allowed. Rendered in the pay page's "Additional Information".
usage_typestringmultiplemultiple = reusable by any number of payers. single = closes after the first successful payment.
expires_atdatetimenullLink stops accepting payments after this time. Must be in the future. Format YYYY-MM-DD HH:MM:SS.
team_bank_account_idintegerteam defaultSettlement account. Must be one of your team's verified bank accounts.
collect_phonebooleantrueWhether the payer must enter a phone number.
note_enabledbooleanfalseShow an extra note field to the payer.
note_labelstring (≤100)nullLabel for the note field. Required when note_enabled is true.
redirect_urlurl (≤2048)nullBrowser is redirected here after payment. Falls back to the Herepay receipt page if empty.
callback_urlurl (≤2048)nullServer‑to‑server webhook fired when the payment settles (see Callback).
notify_emailemail (≤255)nullEmail to notify about the link (reserved).
payer_namestring (≤255)nullPrefills the Full Name field on the pay page.
payer_emailemail (≤255)nullPrefills the Email field on the pay page.
payer_phonestring (≤32)nullPrefills the Phone Number field on the pay page.

Payer prefill. When payer_name / payer_email / payer_phone are set, the pay page opens with the payer form already filled in — the payer can still edit the values before paying. The prefill is stored on the link itself, so it's intended for usage_type: single links created for a specific customer; on a multiple link every payer would see the same prefilled details.


Examples

Minimal

curl -X POST https://uat.herepay.org/api/integration/create-payment-link \
  -H "SecretKey: <your-team-secret-key>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Consultation Fee",
    "amount": 10.50
  }'

Full

curl -X POST https://uat.herepay.org/api/integration/create-payment-link \
  -H "SecretKey: <your-team-secret-key>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "title": "Order #A1042",
    "amount": 89.90,
    "description": "<p>1x Premium Plan — annual</p>",
    "usage_type": "single",
    "expires_at": "2026-12-31 23:59:59",
    "collect_phone": true,
    "note_enabled": true,
    "note_label": "Booking reference",
    "redirect_url": "https://integrator.example.com/return",
    "callback_url": "https://integrator.example.com/webhook/herepay",
    "notify_email": "sales@integrator.example.com",
    "payer_name": "Aisyah binti Ahmad",
    "payer_email": "aisyah@example.com",
    "payer_phone": "0123456789"
  }'

Response

Success — 200 OK

{
    "status": 200,
    "data": {
        "id": 6,
        "code": "539ace2630bf7fa2",
        "title": "Order #A1042",
        "amount": 89.9,
        "usage_type": "single",
        "status": "active",
        "expires_at": null,
        "redirect_url": "https://integrator.example.com/return",
        "callback_url": "https://integrator.example.com/webhook/herepay",
        "payer_name": "Aisyah binti Ahmad",
        "payer_email": "aisyah@example.com",
        "payer_phone": "0123456789",
        "pay_url": "https://uat.herepay.org/herepay/pay/EQFYRVJXFhhCVUwoXwMlYQ"
    }
}
FieldDescription
idInternal payment‑link id.
codePublic link code.
statusactive, inactive, expired, or completed.
expires_atISO‑8601 or null.
pay_urlRedirect your customer here to pay.

Errors

HTTPBodyWhen
401{ "status": "Unauthorized", "status_code": "41", "error": "..." }Missing / invalid SecretKey.
422{ "status": 422, "error": { "field": ["message"] } }Validation failed.
500{ "status": 500, "error": "Failed to create payment link." }Server error.

Validation example:

{
    "status": 422,
    "error": {
        "title": ["The title field is required."],
        "amount": ["The amount field is required."]
    }
}

Payment flow

  1. CreatePOST this endpoint → receive pay_url.
  2. Redirect — send your customer to pay_url (HTTP 302, or open in a browser).
  3. Pay — the customer completes the payment on the Herepay pay page via FPX.
  4. Return — after payment, Herepay:
    • redirects the customer's browser to your redirect_url (or the Herepay receipt page if you didn't set one), and
    • sends a server‑to‑server callback to your callback_url (if set).

Each link uses its own redirect_url / callback_url. If a link doesn't set them, Herepay falls back to your team‑level URLs.


Callback (webhook)

When a link payment settles, Herepay POSTs (as application/x-www-form-urlencoded) to the link's callback_url.

Payload

FieldDescription
reference_codeInvoice reference code.
payment_codePayment reference code.
transaction_idFPX transaction id (may be empty).
statusSuccess / Failed / Pending.
status_code00 success, 30 failed, 29 pending.
messageGateway remark.
amountPaid amount (MYR).
currencyMYR.
payment_methodPayment gateway name.
fpx_typeFPX type (may be empty).
bank_namePayer's bank (may be empty).
checksumHMAC signature — see below.

Verifying the checksum

The checksum lets you confirm the callback really came from Herepay:

  1. Take all payload fields except checksum.
  2. Sort them by key (ascending).
  3. Join the values with a comma , (in the sorted‑key order). Array values are json_encoded first.
  4. Compute HMAC‑SHA256 of that string using your team's private key.
  5. Compare (constant‑time) against the received checksum.
checksum = HMAC_SHA256( implode(",", values_sorted_by_key), team_private_key )

Respond 200 OK to acknowledge. Herepay logs a failure if your endpoint errors or times out (5s).


Notes

  • Amounts are in MYR with two decimals.
  • usage_type: single links close after the first successful payment; reusable links (multiple) can be paid any number of times.
  • The pay_url code is encrypted — it reveals nothing about the underlying record and is the same URL space used by custom invoices.
  • The link's optional tip/contribution section is shown on the pay page.