Creating Transactions
When a customer buys one of your Deals products, we call your callback API to create the transaction. This is part of the standard callback API you already host; there is no separate Deals service to stand up.
POST https://api.your-company.com/trx/transaction
One call covers exactly one product. The transaction UUID travels in the body as trx_id.
200 is the approval gateWe do not approve the transaction or disburse until this call succeeds. Your success response is the confirmation that you have accepted the order; only then does money move on our side.
So the ordering is: you accept → you respond 200 → we disburse. Return 200 only once the
order is durably committed on your side, and return an error if it is not.
What we send
{
"order_id": "order-123",
"trx_id": "9f1c2b7a-3e5d-4c11-8a6f-2b9d0e7c1a42",
"product_id": "1000001",
"amount": 24999,
"currency": "PHP",
"created": "2026-07-23T08:30:00+08:00",
"customer": {
"full_name": "Juan Dela Cruz",
"first_name": "Juan",
"last_name": "Dela Cruz",
"email": "[email protected]",
"phone": "+639171234567",
"adr_shipping": {
"addr_type": "shipping",
"country": "PH",
"region": "NCR",
"province": "Metro Manila",
"city": "Makati",
"barangay": "Poblacion",
"street": "123 Rizal St.",
"postal_code": "1210",
"address": "123 Rizal St., Poblacion, Makati, Metro Manila 1210"
}
}
}
product_id is the same id you sync to us. order_id is our order reference; store it,
you send it back on every delivery-status update. trx_id is the transaction UUID and goes
in the path of those updates.
customer is the recipient. For gift purchases such as vouchers we also send a sender
object with the buyer's details; it is absent otherwise.
What you return
{ "status": "OK", "in_stock": 41 }
in_stock is the remaining quantity after this order. We write it straight into the Deals
catalog, so return the true post-decrement count. 0 marks the product out of stock immediately,
with no separate sync call needed.
Out of stock
If you cannot fulfil because the product is out of stock, do not create the transaction. Return
409:
{ "code": "OUT_OF_STOCK", "message": "Product is out of stock" }
We match on code, so message is yours to word however you like. This is a soft failure: we
set the product's stock to 0 and cancel the transaction quietly, without treating it as an
integration error.
One attempt, no retries
We do not retry POST /trx/transaction. Each transaction order is attempted a single time.
We wait up to 40 seconds for your response; if none arrives we stop waiting and treat the call
as failed.
If the call does not clearly succeed (any 4xx or 5xx, or the 40-second timeout), we treat the
order as failed and cancel the customer's transaction on our side. We do not approve and we do
not disburse.
Because there is only ever one attempt, return 200 only once the order is durably committed on
your side. A late or uncertain response is safer failed than accepted: if your 200 does not reach
us within the 40 seconds we cancel, so a success that arrives too late leaves you holding an order
we have already cancelled. The outcome is visible in the
Merchants Portal.
To settle a case where you are unsure whether your response reached us, read our view of the transaction back:
GET /trx/{id}/status
APR means we approved and disbursed; anything else means we did not. GET /trx/{id}/history
gives the full timestamped sequence. Both are on the
Billease Transaction API and need no extra setup.
Existence check (manual, for debugging)
You also host a lightweight, read-only endpoint we can use to check whether a transaction order
reached you. It exists purely for manual debugging on our side; nothing automated calls it, and
it plays no part in approval or disbursement. Your 200 on POST /trx/transaction is still the only
approval gate; this is not a confirmation step.
GET https://api.your-company.com/trx/transaction/{trx_id}
{trx_id} is the transaction UUID we sent you on POST /trx/transaction. As with the POST endpoint,
the exact path is yours to choose; just give it to us at onboarding. Secure it with the same
scheme as your other callback endpoints.
We look only at the HTTP status and ignore the response body: any 2xx means the order exists on
your side; any 4xx / 5xx means it does not, or could not be confirmed.
Checking the price
We do not require you to verify amount, and we do not verify it either. But a price change on
your side goes through our approval queue, so the Deals catalog price can lag yours for as long as
approval takes.
Compare amount against your live price before accepting, and reject rather than confirming at
a stale one; remember that your 200 is what triggers disbursement.
Cancelling
A Deals order cannot be cancelled or reversed with a status. It is already approved on our
side, so POST /trx/{id}/update with status: CAN, or any other status value, does not change
the transaction: such calls are rejected. (Standard checkout differs, where status: CAN cancels
the transaction.) The status field is inert here; you still send delivery_status to report
fulfilment progress.
Any reversal must go through a refund, whether or not the order has already shipped:
POST /trx/{id}/refund
It settles the amount, marks the items refunded, folds into your net-proceeds accounting and returns
a refund_id you can poll with GET /trx/refund/{refund_id}. See
POST /trx/{id}/refund.