Flow · 13 steps
Store credit and gift cards
Balances customers hold, as tenders: give a customer store credit and take it back, issue a gift card and look its code up, pay an order with the card, refund part of it back onto the card the money came from, and stop the card.
A gift card's code is answered once, by the issue (and its retry, the same code): no read shows it again, only its last four. Ids written {giftCardId} are read from an earlier answer.
Retrying each step. The credit, the card, the payment and the refund carry your key (creditId, giftCardId, paymentId, refundId) and answer with what the first call recorded; a reversal and a disable are idempotent by state.
Services involved
A filled dot is a read; a ring is a call that changes something.
- Fulfillment Manager:
https://fulfillment.getmanifold.io - Inventory Manager:
https://inventory.getmanifold.io
Every call carries Authorization: Bearer $MANIFOLD_TOKEN unless its step says otherwise
(getting a token). Run a flow in your sandbox, not your live
organization: see Before you start.
1 Give a customer store credit
Twenty-five dollars for a late delivery, with the reason for the record. Credit is per currency.
POST /credit Fulfillment Manager
{
"creditId": "crd_01a15912-4c01-7f2a-8b3c-4d5e6f7a8b9c",
"holderId": "cmp_01a15912-2b01-7c3d-8e4f-5a6b7c8d9e0f",
"currency": "AUD",
"amountCents": 2500,
"reason": "Late delivery"
}Answers 201. What the answer holds: the operation's example.
Records fulfillment.credit-issued.
2 Read the customer's credit
One account per currency, with its history newest first.
GET /credit?companyId=cmp_01a15912-2b01-7c3d-8e4f-5a6b7c8d9e0f Fulfillment Manager
What the answer holds: the operation's example.
3 Take it back
Issued to the wrong customer: a manual issue reverses once, while the customer still holds it.
POST /credit/crd_01a15912-4c01-7f2a-8b3c-4d5e6f7a8b9c/reverse Fulfillment Manager
{
"reason": "Issued to the wrong account"
}What the answer holds: the operation's example.
Records fulfillment.credit-reversed.
4 Issue a gift card
Fifty dollars. The answer carries the code — give it to the customer now; no later read shows it.
POST /gift-cards Fulfillment Manager
{
"giftCardId": "gcd_01a15912-6e02-7b3c-9d4e-5f6a7b8c9d0e",
"amountCents": 5000,
"currency": "AUD"
}Answers 201. What the answer holds: the operation's example.
From your answer, later steps send code as {code}, card.id as {giftCardId} and card.last4 as {last4}.
Records fulfillment.gift-card-issued.
5 Check the code
What the code is good for, before it pays. A code that matches no card is 404 and counts against you: ten in fifteen minutes and every code is refused for fifteen.
POST /gift-cards/check Fulfillment Manager
{
"code": "{code}"
}What the answer holds: the operation's example.
Records nothing.
6 Find the card by its last four
How staff find a card a customer brings in: never by its whole code.
GET /gift-cards?last4=%7Blast4%7D Fulfillment Manager
What the answer holds: the operation's example.
7 Have something to sell
Ten mugs on hand, so the order below has stock to hold and ship.
POST /items Inventory Manager
{
"sku": "GIFT-WRAP-MUG",
"name": "Gift-wrapped mug",
"quantity": 10
}Answers 201. What the answer holds: the operation's example.
Records inventory.item-created.
8 Take an order
Two mugs at eighteen dollars each, for the gift card to pay towards.
POST /orders Fulfillment Manager
{
"reference": "GIFT-1001",
"lines": [
{
"sku": "GIFT-WRAP-MUG",
"quantity": 2,
"unitPriceCents": 1800
}
],
"customer": {
"personId": "psn_01a15890-1b2c-7d3e-8f4a-5b6c7d8e9f0a"
}
}Answers 201. What the answer holds: the operation's example.
From your answer, later steps send id as {orderId}.
Records fulfillment.order-created, fulfillment.stock-allocated, fulfillment.shipment-created.
9 Pay with the gift card
The card's balance falls in the same commit as the order's, under the organization's lock: two payments racing for one card never overdraw it. A card disabled, expired, in another currency or short is refused.
POST /orders/{orderId}/payments Fulfillment Manager
{
"paymentId": "pay_01a15912-8a03-7d4e-8f5a-6b7c8d9e0f1a",
"amountCents": 1800,
"method": "gift-card",
"giftCardCode": "{code}"
}Answers 201. What the answer holds: the operation's example.
Records fulfillment.payment-recorded.
10 Refund part of it, back onto the card
The money goes back the way it came: the card that paid gets it first. The refund's tenders say so.
POST /orders/{orderId}/refunds Fulfillment Manager
{
"refundId": "rfd_01a15912-9b04-7e5f-9a6b-7c8d9e0f1a2b",
"amountCents": 600,
"reason": "Wrap torn",
"lines": []
}Answers 201. What the answer holds: the operation's example.
Records fulfillment.refunded.
11 Stop the card
Reported lost: no payment may draw on it until it is enabled again.
POST /gift-cards/{giftCardId}/disable Fulfillment Manager
{
"reason": "Reported lost"
}What the answer holds: the operation's example.
Records fulfillment.gift-card-disabled.
12 Let it be used again
Found after all: enabled, with its balance as it stood.
POST /gift-cards/{giftCardId}/enable Fulfillment Manager
{}What the answer holds: the operation's example.
Records fulfillment.gift-card-enabled.
13 Read the card
Its balance — fifty less the payment plus the refund — and its whole history, never its code.
GET /gift-cards/{giftCardId} Fulfillment Manager
What the answer holds: the operation's example.
What a recorded fact is: Facts and the journal. Why a repeated step changes nothing: Idempotency and retries.