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
searchstringFilter by customer name or email.
sortstringSort order. One of: created_asc, created_desc, amount_asc, amount_desc.
payment_statusstringFilter by status: created, pending, paid, failed, cancelled, part-refunded, refunded, expired, errored.
start_datestringStart date (Y-m-d).
end_datestringEnd date (Y-m-d).
per_pageintegerResults 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_amountintegeryesAmount in GB pence. Minimum 5.
referencestringnoMerchant reference shown on the bank statement. Max 18 chars.
reasonstringnoInternal 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
200Refund created (pending dashboard approval)
400Refund exceeds available amount or other validation failure
401Invalid or missing API token
404Order not found

Validation error payload:

{
    "error": true,
    "message": "Validation failed",
    "invalid_fields": {
        "refund_amount": ["Refund amount cannot exceed remaining amount refundable"]
    }
}

Next steps

  • Customers — manage the customer records linked to your orders.
  • Webhooks — receive real-time notifications when payment status changes.