Orders & Refunds
The Orders API lets you list, inspect, and refund transactions. Every Quick Pay or reusable-link payment creates an order that can be retrieved and managed through these endpoints.
List orders
Retrieve a paginated list of orders. Supports searching, sorting, filtering by payment status, and date range. Default pagination is 25 results per page (max 1000).
Request
GET /v2/orders
Query parameters
| Parameter | Type | Description |
|---|---|---|
search | string | Filter by customer name or email. |
sort | string | Sort order. One of: created_asc, created_desc, amount_asc, amount_desc. |
payment_status | string | Filter by status: created, pending, paid, failed, cancelled, part-refunded, refunded, expired, errored. |
start_date | string | Start date (Y-m-d). |
end_date | string | End date (Y-m-d). |
per_page | integer | Results per page (default 25, max 1000). |
Response
{
"data": [
{
"id": "ed6de936",
"total": 1000,
"total_formatted": "£10.00",
"order_status": "paid",
"amount_refundable": 1000,
"amount_pending_refund": 0,
"amount_refunded": 0,
"ordered_at": "2024-03-05T11:50:43.000000Z",
"created_at": "2024-03-05T11:50:43.000000Z",
"updated_at": "2024-03-05T11:55:00.000000Z",
"customer": {},
"payments": [],
"order_lines": []
}
],
"links": {
"first": "https://api.wonderful.one/v2/orders?page=1",
"last": null,
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"path": "https://api.wonderful.one/v2/orders",
"per_page": 25,
"to": 1
}
}
Example
curl --request GET \
--get "https://api.wonderful.one/v2/orders?payment_status=paid&sort=created_desc&per_page=10" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL("https://api.wonderful.one/v2/orders");
const params = { payment_status: "paid", sort: "created_desc", per_page: "10" };
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
fetch(url, {
headers: {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
},
})
.then(response => response.json())
.then(data => console.log(data.data));
$client = new \GuzzleHttp\Client();
$url = 'https://api.wonderful.one/v2/orders';
$response = $client->get($url, [
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'payment_status' => 'paid',
'sort' => 'created_desc',
'per_page' => 10,
],
]);
$body = json_decode((string) $response->getBody());
print_r($body->data);
Show a single order
Retrieve the full details of an order, including the associated customer, payments, and order lines.
Request
GET /v2/orders/{id}
Response
{
"data": {
"id": "ed6d3016",
"total": 8957,
"total_formatted": "£89.57",
"order_status": "paid",
"amount_refundable": 8957,
"amount_pending_refund": 0,
"amount_refunded": 0,
"ordered_at": "2024-03-05T11:50:43.000000Z",
"created_at": "2024-03-05T11:50:43.000000Z",
"updated_at": "2024-03-05T11:55:00.000000Z",
"customer": {
"id": "89650465",
"first_name": "Jane",
"last_name": "Doe",
"full_name": "Jane Doe",
"email": "[email protected]"
},
"payments": [
{
"id": "ed6d3016",
"amount": 8957,
"amount_formatted": "£89.57",
"status": "completed",
"reference": "ORDER-1234",
"pay_link": "https://api.wonderful.one/pay/AB12"
}
],
"order_lines": [
{
"id": "ed6d87e6",
"quantity": 1,
"description": "Gorgeous Fresh Soap",
"price": 8957,
"price_formatted": "£89.57"
}
],
"refunds": []
}
}
Example
curl --request GET \
--get "https://api.wonderful.one/v2/orders/ed6d3016" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
fetch("https://api.wonderful.one/v2/orders/ed6d3016", {
headers: {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
},
})
.then(response => response.json())
.then(data => {
const order = data.data;
console.log(order.customer.email);
console.log(order.payments[0].status);
console.log(order.order_lines[0].description);
});
$client = new \GuzzleHttp\Client();
$response = $client->get('https://api.wonderful.one/v2/orders/ed6d3016', [
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]);
$body = json_decode((string) $response->getBody());
$order = $body->data;
echo $order->customer->email;
echo $order->payments[0]->status;
echo $order->order_lines[0]->description;
Create a refund
Refunds are created against an order and must be approved in your Wonderful dashboard before being sent. The total of all refunds (pending + completed) cannot exceed the original payment amount.
If the customer's bank did not supply refund account details at the time of payment, the API may reject the refund. In that case the merchant should arrange an offline refund.
Request
POST /v2/orders/{id}/refund
Content-Type: application/json
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
refund_amount | integer | yes | Amount in GB pence. Minimum 5. |
reference | string | no | Merchant reference shown on the bank statement. Max 18 chars. |
reason | string | no | Internal note (not shown to the customer). Max 255 chars. |
Response
{
"data": {
"id": "3ed6d864",
"order_id": "ed6d3016",
"refund_amount": 500,
"refund_amount_formatted": "£5.00",
"status": "created",
"reference": "REF-001",
"reason": "Item returned, too big",
"created_at": "2024-04-08T15:05:46.000000Z",
"updated_at": "2024-04-08T15:05:46.000000Z"
}
}
Example
curl --request POST \
"https://api.wonderful.one/v2/orders/ed6d3016/refund" \
--header "Authorization: Bearer {YOUR_AUTH_KEY}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"refund_amount": 500,
"reference": "REF-001",
"reason": "Item returned, too big"
}'
fetch("https://api.wonderful.one/v2/orders/ed6d3016/refund", {
method: "POST",
headers: {
"Authorization": "Bearer {YOUR_AUTH_KEY}",
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify({
refund_amount: 500,
reference: "REF-001",
reason: "Item returned, too big",
}),
})
.then(response => response.json())
.then(data => console.log(data.data));
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.wonderful.one/v2/orders/ed6d3016/refund', [
'headers' => [
'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'refund_amount' => 500,
'reference' => 'REF-001',
'reason' => 'Item returned, too big',
],
]);
$body = json_decode((string) $response->getBody());
$refund = $body->data;
echo "Refund {$refund->refund_amount_formatted} ({$refund->status})";
Error handling
| Status | Meaning |
|---|---|
200 | Refund created (pending dashboard approval) |
400 | Refund exceeds available amount or other validation failure |
401 | Invalid or missing API token |
404 | Order not found |
Validation error payload:
{
"error": true,
"message": "Validation failed",
"invalid_fields": {
"refund_amount": ["Refund amount cannot exceed remaining amount refundable"]
}
}