Receipts
Generate a branded, view-only receipt for a completed payment with one API call. MoneyHash returns a hosted receipt URL. Your customer opens it in a browser and can download it as a PDF.
You trigger receipt creation and deliver the link to your customer yourself - by email, SMS, WhatsApp, or any channel you use.
When to use it
Create a receipt from your success webhook handler: when MoneyHash tells you a payment succeeded, call the Receipts API with the intent ID and hand the returned URL to your customer.
Diagram: payment → success webhook → POST /api/v1.4/receipts → embed_url → customer.
For how to receive and verify your success webhook, see Webhooks and Payment Webhook.
Before you start
| Step | Where |
|---|---|
| Configure the receipt content: document title, company name and address, VAT/CR number, header, footer, terms | Dashboard → Checkout Studio → Receipt tab |
| Configure colours and logo | Checkout Studio branding. Receipts inherit it. |
| Test without real payments | Use your test API key. See Sandbox. |
Later changes in Checkout Studio apply only to receipts created afterwards. Existing receipts never change.
Sandbox
Receipts created with a test API key carry is_live: false. The same base URL serves test and live; the key decides which mode a request runs in. See Integration Modes and Sandbox.
Create a receipt
Receipts use the same base URL and authentication as the rest of the MoneyHash API. Send requests to https://web.moneyhash.io/api/v1.4/ with your account API key in the x-api-key header. The same base URL serves test and live; the key decides the mode. See Programmatic Access.
Request fields
| Field | Type | Required | Notes |
|---|---|---|---|
payment_source | string | No | MONEYHASH |
reference | string | No | The receipt number shown to your customer. Unique per account. Auto-generated if omitted. |
receipt_data | object | Yes | The receipt content. See below. |
receipt_data
receipt_data| Field | Type | Required | Notes |
|---|---|---|---|
intent_id | string | Yes | The intent must have a successful purchase or authorize transaction. |
amount | number | Ignored | Always taken from the intent transaction. |
amount_currency | string | Ignored | Always taken from the intent transaction. |
paid_at | ISO 8601 | Ignored | The success time of the intent transaction. |
customer | UUID | Optional | A MoneyHash Customer ID. Used to fill customer details. |
customer_details | object | Optional | name, email, phone_number, tax_id. Overrides customer. |
product_items | array | Optional | See product_items[]. |
fees | array | Optional | See fees[]. |
Anything you send for amount, amount_currency or paid_at is ignored. These always come from the intent transaction.
product_items
product_items| Field | Type | Notes |
|---|---|---|
name | string | Line name |
amount | number | Unit amount |
quantity | integer | |
description | string | Optional |
category, subcategory, type | string | Optional |
fees
fees| Field | Type | Notes |
|---|---|---|
title | object | Localized: { "en": "...", "ar": "...", "fr": "..." } |
value | number | Fee amount |
Use fees for the subtotal, VAT, shipping, handling, or any other line shown under the items.
Amounts render exactly as you send them.
How MoneyHash fills in the receipt
What you send takes priority over what the intent holds - except amount, currency and paid-at, which always come from the intent transaction.
| Field | Where it comes from, in order |
|---|---|
amount, amount_currency | The intent transaction only |
paid_at | The success time of the intent transaction |
product_items | Your payload → the intent |
fees | Your payload → the intent |
customer_details | Your customer_details → your customer ID → the intent's customer |
Diagram: which source wins for each receipt field.
Values are resolved when the receipt is created and stored. They cannot be changed afterwards.
Examples
{
"reference": "REC-MH-500",
"receipt_data": {
"intent_id": "gNWnNBq"
}
}{
"reference": "REC-MH-50",
"receipt_data": {
"intent_id": "19zGjLY",
"customer_details": {
"name": "Ahmed Khalid",
"email": "[email protected]",
"phone_number": "+966500000000",
"tax_id": "310000000000003"
},
"product_items": [
{ "name": "Postpaid line — September 2026", "description": "Test product description", "amount": 45.00, "quantity": 1 }
],
"fees": [
{ "title": { "en": "VAT 15%", "ar": "ضريبة القيمة المضافة ١٥٪" }, "value": 5.00 }
]
}
}Example response
{
"status": {
"code": 200,
"message": "success",
"errors": []
},
"data": {
"id": "e5d92f6e-a45d-41b7-8279-13dc91b5bdce",
"payment_source": "MONEYHASH",
"reference": "REC-MH-500",
"embed_url": "https://embed.moneyhash.io/link/receipt/e5d92f6e-a45d-41b7-8279-13dc91b5bdce",
"intent_id": "gNWnNBq",
"amount": 500,
"amount_currency": "AED",
"paid_at": "2026-11-03T10:51:41.912938+00:00",
"is_live": true,
"created_at": "2026-11-10 04:58:59.786035+00:00"
},
"count": 1,
"next": null,
"previous": null
}amount, amount_currency and paid_at come from the intent transaction, whatever you send for them. If you omit reference, MoneyHash generates one. Send the embed_url to your customer.
Response
| Field | Notes |
|---|---|
id | The receipt ID. Use it to retrieve the receipt. |
payment_source | MONEYHASH |
reference | Your reference, or the auto-generated one. |
embed_url | The hosted receipt page. Send this to your customer. |
intent_id | The intent the receipt was created for. |
amount | The amount taken from the intent transaction. |
amount_currency | The currency taken from the intent transaction. |
paid_at | The success time of the intent transaction. |
is_live | false for receipts created with a test key. |
created_at | When the receipt was created. |
embed_url can view the receipt
Do not publish it. Send it only to the customer it belongs to.
Retrieve a receipt
Returns the full stored receipt plus the brand_settings that were applied when it was created: a snapshot of your Checkout Studio branding.
{
"status": {
"code": 200,
"message": "success",
"errors": []
},
"data": {
"account": "Test Account",
"receipt_data": {
"id": "e5d92f6e-a45d-41b7-8279-13dc91b5bdce",
"payment_source": "MONEYHASH",
"reference": "REC-MH-500",
"fees": null,
"amount": 500,
"paid_at": "2026-11-03T10:51:41.912938+00:00",
"product_items": null,
"amount_currency": "AED",
"customer_details": {
"name": "test customer",
"email": "[email protected]",
"tax_id": null,
"phone_number": "+201234567891"
}
},
"brand_settings": {
"brand_primary_color": "#1E3A8A",
"brand_accent_color": "#F4C542",
"icon": "https://www.example.com/icons/e3ba5.png",
"privacy_policy": "https://www.example.com/Privacy-Policy",
"terms_of_service": "https://www.example.com/Terms-of-Service",
"light": {
"brand_color": "#1E3A8A",
"accent_color": "#F4C542",
"background_color": "#ffffff",
"header_color": "#ffffff",
"primary_text_color": "#444444",
"secondary_text_color": "#6b7280",
"border_color": "#e5e7eb"
},
"dark": {
"brand_color": "#23395b",
"accent_color": "#ffe3c3",
"background_color": "#18181b",
"header_color": "#18181b",
"primary_text_color": "#fafafa",
"secondary_text_color": "#a1a1aa",
"border_color": "#27272a"
},
"font_family": "Inter",
"corner_radius": "regular",
"logo_position": "left",
"extra_methods": "collapsed",
"saved_cards_display": "dropdown",
"methods_layout": "accordion",
"card_form_format": "expanded",
"visibility": {
"logo": false,
"summary_sidebar": true,
"payment_form_title": true,
"payment_selector_title": true
},
"copy": {
"receipt": {
"footer": {
"ar": "",
"en": "",
"fr": ""
},
"header": {
"ar": "",
"en": "",
"fr": ""
},
"address": {
"ar": "",
"en": "",
"fr": ""
},
"cr_number": "",
"sub_header": {
"ar": "",
"en": "",
"fr": ""
},
"vat_number": "",
"company_name": {
"ar": "",
"en": "",
"fr": ""
}
}
},
"apple_pay": {
"merchant_name": ""
},
"icon_dark": null
}
},
"count": 1,
"next": null,
"previous": null
}The hosted receipt page
| Behaviour | Detail |
|---|---|
| Access | Anyone with the embed_url. Do not publish it, send it only to the customer it belongs to. |
| Content | Your Checkout Studio receipt content and branding, the reference, the customer (omitted if none), items, fees, totals, paid date, and terms/footer |
| No items sent | One line is generated: quantity 1, amount equal to the payment amount |
| A download button on the page. Same content and layout as the page. | |
| Payment actions | None. The page never shows a checkout or a payment method. |
Rules and errors
When a create request fails validation, the response comes back in this shape. Each entry in errors pairs a field name with a message:
{"status": {"code": 400, "message": "", "errors": [{"<field>": "<message>"}]}, "data": {}, ...}Create a receipt
Top-level fields
| Field | Message | When |
|---|---|---|
receipt_data | This field is required. | It is missing |
non_field_errors | Invalid data. Expected a dictionary, but got str. | receipt_data is not an object |
payment_source | "X" is not a valid choice. | MONEYHASH. This is the default, so you can omit it. |
reference | Ensure this field has no more than 255 characters. | It is longer than 255 characters |
reference | A receipt with this reference already exists for the account. | The reference is already used on this account |
intent_id
| Field | Message | When |
|---|---|---|
intent_id | This field is required. | It is missing |
intent_id | Intent not found. | The ID does not exist, belongs to another account, or is in the other mode (live or test) |
intent_id | Intent has no active transaction. | The intent has no active transaction |
intent_id | The active transaction doesn't have a successful purchase or authorize operation. | The intent has not been paid or authorized |
An intent created in live mode cannot be used with a test key, and the other way around. Both cases return Intent not found.
Optional fields
| Field | Message |
|---|---|
customer | Must be a valid UUID. / Customer not found. (the customer is not in this organization or this mode) |
customer_details | Enter a valid phone number. / Enter a valid email address. |
product_items | This field is required. for name, amount, description and quantity; Subcategory and type are required; Category, Subcategory and type combination is not supported; number and range errors on the amount fields (minimum 0, up to the maximum amount) |
fees | title: This field is required. (title.en is required). value: A valid number is required. |
Retrieve a receipt
| HTTP | Error | When |
|---|---|---|
| 404 | {"error": "Receipt not found."} | The receipt does not exist, belongs to another account, or is in the other mode |
The 404 response body does not follow the status / errors shape shown above. Handle it separately in your error parsing.
Other rules
| Case | Result |
|---|---|
| Edit, void or delete a receipt | Not supported. A receipt is permanent once created. |
MoneyHash does not calculate tax or validate line items, fees or totals.
Common errors and troubleshooting
Related pages
- Webhooks and Payment Webhook - trigger receipt creation from your success webhook.
- Webhooks Signature - verify the webhook before creating a receipt.
- Programmatic Access - API keys and base URL.
- Integration Modes (Test vs Live) and Sandbox - test receipts before going live.
Updated about 10 hours ago