Orders & Postbacks › Postbacks
Postbacks
A postback is a signed POST request PriceFirst sends to your postbackUrl the moment a customer completes a trade-in. You acknowledge receipt by returning HTTP 200 with your internal transaction ID in the body. Retries, signing and idempotency are documented on separate pages.
End-to-end flow
- Customer completes checkout on
pricefirst.com. - PriceFirst creates the order with status
pendingand generates a shortorder_code(e.g.58BDGJ97) for customer-facing references. - In the background, PriceFirst POSTs the payload to your
postBackUrlwith HMAC-signed headers. - You respond HTTP 200 with a JSON body
{ status: 200, order_id }within 30 seconds. - PriceFirst stores the transaction ID, marks the order
delivered, and emails a trade-in confirmation to the customer. - If delivery fails, PriceFirst logs the attempt, marks the order
failed, and (unless retries are disabled) queues a retry with exponential backoff. See Retries & Idempotency.
Endpoint registration
Each marchat/business registers a single HTTPS URL on their marchant profile:
| Field | Description |
|---|---|
postBackUrl | Your postback endpoint. HTTPS only. |
postbackToken | Shared secret sent as X-PriceFirst-Token. Auto-generated on marchat save. |
postbackHmacSecret | HMAC-SHA256 secret, used to sign the body. Auto-generated on marchat save. |
postbackRetryEnabled | Whether failed postbacks are automatically retried. Default true. |
postbackMaxAttempts | Maximum total delivery attempts (including the first). Default 6. |
postbackToken and postbackHmacSecret are given once during onboarding. Store them and use them to verify every incoming postback — see Signing & Security.
Request
- Method:
POST - URL: Marchants
postBackUrl - Content-Type:
application/json - Timeout: 30 s
- Headers sent (see Signing & Security for the full spec):
| Header | Example |
|---|---|
User-Agent | PriceFirst-OrderSystem/1.0 |
X-PriceFirst-Token | pWvT1… shared secret |
X-PriceFirst-Timestamp | 1714752100 (Unix seconds) |
X-PriceFirst-Signature | a0f3… HMAC-SHA256 hex |
X-PriceFirst-Algorithm | HMAC-SHA256 |
X-PriceFirst-Idempotency | 58BDGJ97 (same as order_code) |
Payload
BACS / bank transfer example:
{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+447700900000",
"postcode": "ME14BJ",
"address": "7 Ashford Road",
"additionalAddress": "Sterling House",
"city": "Maidstone",
"country": "United Kingdom",
"recycler_name": "We Buy Any Phone",
"device_category": "Mobile Phones",
"device_id": "PF-67e144bc64b5fa0aba8e5236",
"device_name": "iphone 16e",
"device_price": 350,
"device_assessment": {
"storage": "128gb",
"condition": "excellent",
"network": "unlocked"
},
"payment_method": "bacs",
"bank_account_name": "Jane Doe",
"bank_sort_code": "123456",
"bank_account_number": "12345678",
"postage_option": "free_post_bag",
"order_code": "58BDGJ97"
}PayPal example (only the payment fields change):
{
"payment_method": "paypal",
"paypal_email": "jane.paypal@example.com"
}Field reference
| Field | Type | Notes |
|---|---|---|
name | string | Customer name, snapshot at order time. |
email | string | Canonical customer email. |
phone | string | E.164 recommended. |
postcode | string | UK postcode of the sender address. |
address | string | Street address line 1. |
additionalAddress | string/optional | Address line 2. |
city | string | City / town. |
country | string | Defaults to United Kingdom. |
recycler_name | string | Your company or marchant name. |
device_category | string | System category (Mobile Phones, iPad, …). |
device_id | string | The Device ID you supplied in your feed. |
device_name | string | Lowercased model string from the feed. |
device_price | number | Price locked at order time (GBP, already 50p-rounded). |
device_assessment | object | { storage, condition, network } — all normalised slugs. |
payment_method | bacs | paypal | Determines which payment fields are present. |
bank_* | strings | Present when payment_method = bacs. |
paypal_email | string | Present when payment_method = paypal. |
postage_option | enum | free_post_bag or free_post_label. |
order_code | string | Short, customer-facing unique ID (8 chars). Use in UI / support. |
Always dedupe on order_code (which matches the X-PriceFirst-Idempotency header). It's guaranteed unique and safe to use as your external order reference.
Response
Your endpoint must respond with:
- HTTP status
200 OK(any other status is treated as a failure). Content-Type: application/json.- A JSON body with:
status— the number200(must match the HTTP status).order_id— your internal transaction / order identifier as a non-empty string (up to 256 chars).
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": 200,
"order_id": "TX-1029384756"
}
Additional keys are allowed and ignored.
Plain-text bodies, empty bodies, and { ok: true }-style acknowledgements are all treated as failures. The body must be a JSON object containing both status: 200 and a non-empty order_id string. See the Test Harness error codes for a full list of rejection reasons.
Error responses
If you can't process the postback, return a non-200 HTTP status with a JSON body describing the problem:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"status": 401,
"error": "bad_signature",
"message": "HMAC signature did not match"
}
PriceFirst does not parse error bodies beyond logging them — any non-200 HTTP status simply triggers the retry pipeline. Use meaningful codes (400 bad payload, 401 bad token/signature, 409 duplicate, 422 validation, 5xx your problem).
Postage options
postage_option value | Description |
|---|---|
free_post_bag | Customer has chosen a physical postage bag. |
free_post_label | Customer has chosen a postage label via email. |
Further postage options (courier collection + collection_date) are not currently supported. They are reserved for a future release and this doc will be updated accordingly.
Conditions
device_assessment.condition is the normalised base condition — one of new, excellent, good, poor, broken. See Recycling Feeds for the alias map. If you need the marchant-supplied label from your feed, look it up via device_id.
Next
- Signing & Security — HMAC verification, token rotation.
- Retries & Idempotency — backoff schedule, attempt history.
- Postback Test Harness — signed sample payload generator.