Payments
See currencies for more information on providing and using currency values. All values are in lowest denomination.
List Payments
List payments
Scope: payments:read
get /organizations/{organizationId}/paymentsParameters
| Name | Type | In | Description |
|---|---|---|---|
organizationId | string | path | Organization ID |
locationId | string | query | Location ID |
ref | string | query | Only return payments with this reference (e.g. the ref used to create a terminal payment). Results are ordered newest first. |
sort | string | query | Sort the resulting payments by created or updated timestamp (most recent first). Defaults to created. "created", "updated" |
after | string | query | The cursor to use for pagination. Do not use this field manually it will be automatically provided in the response headers (see Paging guide). |
Responses
| Header | Description |
|---|---|
X-Next-Page | URL of the next page of results, see Paging |
X-Prev-Page | URL of the previous page of results, see Paging |
[
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "AUD",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
},
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "AUD",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
},
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "AUD",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
},
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "AUD",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Non dolorem quidem cum.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
}
]Examples
Finding a payment by reference
To find the payment created for a terminal payment, pass the ref you used to create it as the ref query parameter.
Only payments with that reference are returned, ordered newest first (sort is ignored when ref is provided). You may combine it with locationId.
If more results are available, continue with the X-Next-Page header as described in the Paging guide.
GET /organizations/{organizationId}/payments?ref=my-pos-ref
Syncing payments on a schedule
To sync the full historical set of payments on a schedule (rather than using webhook events) without needing to refetch all payments you may use the sort=updated query parameter.
This will fetch payments starting with those updated most recently. Typically this is the timestamp when the payment last changed state.
Continue to fetch next pages until you pass the updated timestamp from the last scheduled run.
The following example demonstrates the approach using fetch in Typescript (note: limited error handling for brevity).
async function getUpdatedPayments(organizationId: string, updatedAt: Date | null) {
let payments = [];
let path: string | null = `/organizations/${organizationId}/payments?sort=updated`;
do {
const url = new URL(path, "https://api.loke.global");
const response = await fetch(url, {
headers: { Authorization: "Bearer my_access_token" },
});
if (!response.ok) throw new Error("Network response was not OK");
path = response.headers.get("X-Next-Page");
payments.push(await response.json());
const lastPayment = payments[payments.length - 1];
if (!lastPayment || (updatedAt && new Date(lastPayment.updatedAt) < updatedAt)) {
// don't continue, even if more pages
path = null;
}
} while (path);
return { payments, updatedAt: payments[0]?.updatedAt ?? updatedAt };
}
async function doScheduledJob() {
// load the job params, in particular last known updatedAt
const job = await getMyJob();
const {payments, updatedAt} = await getUpdatedPayments(
job.organizationId,
job.updatedAt // will be null on first run
);
// do something with payments
await updatePaymentsInMySystem(payments);
// remember the new updatedAt value for next run
await updateMyJob(job.id, { updatedAt });
}
Partially refunding a payment
A payment can be partially refunded when the payment returned by Get a Payment or List Payments includes both revision and refundableAmount. Payments without them cannot be partially refunded, use Reverse a Payment instead.
GET /organizations/{organizationId}/payments/{paymentId}
{
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"state": "settled",
"refundableAmount": 1000,
"revision": "rev-1"
// ...
}
Refund up to refundableAmount, passing the revision you last saw as expectedRevision.
POST /organizations/{organizationId}/payments/{paymentId}/refund
{
"amount": 400,
"expectedRevision": "rev-1"
}
The response is the updated payment, with state partially_refunded, a reduced refundableAmount and a new revision. Each refund must use the latest revision, so refund the remainder with the new one.
{
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"state": "partially_refunded",
"refundableAmount": 600,
"revision": "rev-2"
// ...
}
{
"amount": 600,
"expectedRevision": "rev-2"
}
Once refundableAmount reaches 0 the payment has state refunded, the same end result as reversing it.
A refund can fail with:
HTTP 400: Bad Requestif theamountis below 1, orexpectedRevisionis missing or malformed.HTTP 404: Not Foundif the payment doesn't exist, including payments taken before the store used LOKE.HTTP 409: Conflictif:- the
expectedRevisionis stale, so re-read the payment and retry with the newrevision - the
amountexceedsrefundableAmount - the payment is still pending, such as a terminal or MOTO payment whose long poll is still active
- another refund is in progress
- the payment provider rejected the refund
- the
The message in the response body describes which case it was.
Get a Payment
Get payment by ID
Scope: payments:read
get /organizations/{organizationId}/payments/{paymentId}Parameters
| Name | Type | In | Description |
|---|---|---|---|
organizationId | string | path | Organization ID |
paymentId | string | path | Payment ID |
Responses
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "SGD",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Ea eos dolore praesentium ut.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Ea eos dolore praesentium ut.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
}Reverse a Payment
Reverse a payment, refunding the customer in full
Scope: payments:write
put /organizations/{organizationId}/payments/{paymentId}/reverseParameters
| Name | Type | In | Description |
|---|---|---|---|
organizationId | string | path | Organization ID |
paymentId | string | path | The unique identifier for the payment |
Request Body
{
"reason": "The store never received the order."
}Responses
Refund a Payment
Refund part of a payment. Multiple refunds may be made until the payment has been fully refunded. For a full refund, use the "reverse" endpoint.
- The expectedRevision should be the revision from the latest version of the payment the user has seen, so a refund is rejected if the payment has changed since.
- The same amount and expectedRevision can be safely retried and will only refund once.
- Responds with a conflict if the expectedRevision is stale, the amount exceeds the remaining refundable amount, the payment is still pending, another refund is in progress, or the payment provider rejects the refund.
- A payment can be partially refunded only if the payment returned by Get or List includes a revision and refundableAmount, and the amount may be up to refundableAmount. Payments without them can only be reversed using the "reverse" endpoint.
- Each refund must use the latest revision, which changes after every refund. While refundableAmount is above 0 the state is partially_refunded, once it reaches 0 the payment is refunded, the same end result as a reverse.
Scope: payments:write
post /organizations/{organizationId}/payments/{paymentId}/refundParameters
| Name | Type | In | Description |
|---|---|---|---|
organizationId | string | path | Organization ID |
paymentId | string | path | The unique identifier for the payment |
Request Body
{
"amount": 500,
"expectedRevision": "3",
"reason": "Garlic bread was missing from the order."
}Responses
{
"billingType": "order/pickup",
"chargedAmount": 600,
"completedAt": "2018-08-08T02:35:21Z",
"createdAt": "2018-08-08T02:35:21Z",
"creditAmount": 200,
"currency": "GBP",
"customer": {
"email": "john@example.com",
"firstName": "John",
"id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
"lastName": "Smith",
"phoneNumber": "+61411222333"
},
"discountAmount": 300,
"discounts": [
{
"amount": 1200,
"name": "Ea eos dolore praesentium ut.",
"taxIncluded": 123
},
{
"amount": 1200,
"name": "Ea eos dolore praesentium ut.",
"taxIncluded": 123
}
],
"externalAmount": 600,
"feeAmount": 10,
"id": "29e13de7-d158-4aba-a928-7d868c1dbfb9",
"items": [
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
},
{
"amount": 450,
"id": "FOOD001",
"name": "Coffee",
"options": [
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
},
{
"choices": [
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
},
{
"amount": 50,
"id": "CSML1",
"name": "Small"
}
],
"id": "OPT01",
"name": "Size"
}
],
"quantity": 2,
"type": "item"
}
],
"locationId": "01HMWZ6W8HK7FHE4H0RJC74M7R",
"payoutAmount": 590,
"refId": "INV123456",
"refundableAmount": 500,
"refundedAt": "2018-08-08T02:35:21Z",
"revision": "3",
"state": "completed",
"tipAmount": 100,
"total": 1000,
"updatedAt": "2018-08-08T02:35:21Z"
}Models
Payment
| Name | Type | Description |
|---|---|---|
| id | string | Payment ID |
| locationId | string | (optional) Unique ID for the location this payment belongs to. May be null on some payments (e.g., promotion purchases). |
| refId | string | (optional) Reference ID provided by payment source (e.g., POS for an order). Not guaranteed to be unique. |
| completedAt | string | (optional) When the payment was completed |
| createdAt | string | When the payment was initiated |
| refundedAt | string | (optional) When the payment was refunded |
| billingType | string | Billing classification of payment, corresponds to the source type (e.g., order/delivery, order/pickup, pos/bill, app/credit) |
| chargedAmount | integer | The amount charged to the customer's payment method (credit card) in the lowest denomination (e.g., cents). This will be the total plus tips, minus any discounts and credits. |
| updatedAt | string | When the payment was last updated |
| creditAmount | integer | The LOKE-applied credit amount in the lowest denomination (e.g., cents). This will be 0 if there is no credit associated with the payment. If multiple credits have been applied this will be the sum of all credits. Exclude external credits. |
| currency | string(enum) | "AUD", "SGD", "GBP", "NZD", "USD" |
| discountAmount | integer | The LOKE-applied discount amount in the lowest denomination (e.g., cents). This will be 0 if there is no discount associated with the payment. If multiple discounts have been applied this will be the sum of all discounts. Exclude external discounts. |
| externalAmount | integer | The amount (to be) paid by an external payment method (cash etc). This is what the chargedAmount would have been if the customer had payed via LOKE. Only one of chargedAmount or externalPaymentAmount will be non-zero. |
| feeAmount | integer | The fee collected and withheld by LOKE for this payment in the lowest denomination (e.g., cents). This will be 0 if there is no fee associated with the payment. |
| payoutAmount | integer | The amount (to be) paid out to the merchant in the lowest denomination (e.g., cents). This will be the chargedAmount minus the feeAmount. |
| refundableAmount | integer | (optional) Amount still refundable to the customer's card and store credit, in the smallest currency unit. Only returned for payments created on the newer payments system; omitted for older payments. |
| revision | string | (optional) Changes each time the payment is updated, it is used for refunds to ensure the user has seen the latest version of the payment. Treat it as an opaque value, its format is liable to change on future payments. Only returned for payments created on the newer payments system; omitted for older payments. |
| state | string | Current state of payment (Current Values: "submitted" | "settled" | "partially_refunded" | "refunded") |
| tipAmount | integer | The tip amount in the lowest denomination (e.g., cents). This will be 0 if the tip was 0 or if there is no tip associated with the payment. |
| total | integer | The total amount in the lowest denomination (e.g., cents). This will be the sum of all the items, external (non-LOKE) discounts, external surcharges, and delivery fees. |
| customer | CustomerTiny | (optional) |
| discounts | PaymentDiscount[] | Discounts applied to the payment |
| items | PaymentLineItem[] |
CustomerTiny
| Name | Type | Description |
|---|---|---|
| id | string | Unique ID of the Customer |
| string | (optional) The Customers email address | |
| firstName | string | Customer first name or given name |
| lastName | string | Customer last name or surname |
| phoneNumber | string | (optional) The Customers mobile phone number |
PaymentDiscount
Specifies the discount that was applied to the Payment.
| Name | Type | Description |
|---|---|---|
| name | string | Name of the discount |
| amount | integer | Amount payment was discounted by, including tax.
Amount is in the lowest denomination (e.g., cents).
Amount should always be an integer value (never decimals). |
| taxIncluded | integer | (optional) Specifies the tax, in the lowest denomination (e.g., cents), that was included in the discount.
This can be null if tax is unknown. |
PaymentLineItem
| Name | Type | Description |
|---|---|---|
| id | string | Product identifier for the item. Depending on the source this could be a SKU, PLU, a database identifier, or something composite. |
| name | string | Item name |
| amount | integer | The amount in the lowest denomination (e.g., cents). This will be the price of a single quantity of the item. |
| quantity | integer | The quantity of identical items purchased on this line. |
| type | string | The type of line item (e.g., item, discount, surcharge) |
| options | PaymentLineItemOption[] | (optional) options chosen for this item |
PaymentLineItemOption
| Name | Type | Description |
|---|---|---|
| id | string | Identifier for the option (group of choices) |
| name | string | Option name (e.g., 'size', 'milk', 'sugar') |
| choices | PaymentLineItemOptionChoice[] | Choices made for this option |
PaymentLineItemOptionChoice
| Name | Type | Description |
|---|---|---|
| id | string | Product identifier for the choice. Depending on the source this could be a SKU, PLU, a database identifier, or something composite. |
| name | string | Choice name (e.g., 'small', 'medium', 'large') |
| amount | integer | The amount of this choice in the lowest denomination (e.g., cents). |
PaymentReversePayload
| Name | Type | Description |
|---|---|---|
| reason | string | The reason for refunding the payment (NOTE: Customers will not see this message). |
PaymentRefundPayload
| Name | Type | Description |
|---|---|---|
| amount | integer | The amount to refund the customer in the lowest denomination (e.g., cents). Must be greater than 0 and no more than the remaining refundable amount. |
| expectedRevision | string | The revision of the payment being refunded, as returned on the Payment. If the payment has changed since, the request fails with a conflict. Retrying with the same expectedRevision is safe and will not refund twice. |
| reason | string | (optional) The reason for refunding the payment (NOTE: Customers will not see this message). |