Your first return

If the items are already here, create the return and process it in two calls. If the customer will send them back, create the return, decide it if still requested, and process it on arrival.

You need a sandbox-bound test key, a paid and fulfilled order, and an active receiving location with a postal address. Use the order's actual line and fulfillment IDs and the receiving location's ID in the examples. The examples assume no matching return policy. They use Flint's built-in changed_mind reason, which needs no setup or buyer note. Return reasons lists all nine built-in IDs.

Items are here#

cURL
curl -X POST https://api.withflintpay.com/v1/returns \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pos-return-create-001" \
  -d '{
    "order_id": "ord_1kmn0aExample",
    "line_items": [{
      "order_line_item_id": "li_1kmn0aExample",
      "requested_quantity": 1,
      "return_reason_id": "rrsn_1T6HXAX0CEXP6YA5K1T392KJE6"
    }]
  }'

The response supplies return_id and line_items[0].return_line_item_id for the processing call. You can also send its version as expected_version to reject a concurrent change. Processing requires all three scopes: commerce.returns.write, commerce.returns.operations.write, and commerce.returns.resolutions.write.

cURL
curl -X POST https://api.withflintpay.com/v1/returns/ret_1kmn0aExample/process \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pos-return-process-001" \
  -d '{
    "completion_behavior": "complete_when_ready",
    "receipt": {
      "receiving_location_id": "loc_1kmn0aExample",
      "source_system": { "source_system_type": "pos", "external_source_id": "store-1042" },
      "received_at": "2026-07-29T14:30:00Z"
    },
    "line_items": [{
      "return_line_item_id": "retli_1kmn0aExample",
      "decision": {
        "decision_basis": "explicit",
        "approved_quantity": 1,
        "return_required_quantity": 1,
        "allowed_resolution_types": ["refund"],
        "selected_resolution_type": "refund",
        "resolution_mode": "automatic",
        "refund_timing": "after_receipt",
        "is_inspection_required": false,
        "receiving_location_id": "loc_1kmn0aExample"
      },
      "received_quantity": 1,
      "resolution": { "resolution_type": "refund", "quantity": 1 }
    }]
  }'

The omitted disposition uses the line's pinned receipt_disposition_mode. The default is automatic, which creates a successful sellable disposition at the receipt's receiving location. Tracked merchandise also creates an inventory receipt and movement. Untracked merchandise has no inventory effect. Send an explicit disposition when the item needs another route. An explicit disposition always wins.

The explicit decision approves one item and requires that item to be handed back. allowed_resolution_types permits a refund; resolution_mode: automatic and selected_resolution_type: refund select it. refund_timing: after_receipt waits for receipt, and is_inspection_required: false lets this example proceed without inspection. receiving_location_id identifies where the item is received. completion_behavior: complete_when_ready lets the return finish when its requirements are met.

For a return already approved by policy, omit both decision and completion_behavior from process. Its decision and completion mode are already committed. A policy-based decision using decision_basis: policy_evaluation requires an applicable return policy; it does not supply defaults for an explicit decision. If an explicit decision changes a valid policy proposal, provide override_reason.

Customer will send items back#

Create the return with the same first request. If its status is still requested, approve it before asking the customer to send the item:

cURL
curl -X POST https://api.withflintpay.com/v1/returns/ret_1kmn0aExample/decide \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: mail-return-decide-001" \
  -d '{
    "completion_mode": "automatic",
    "line_items": [{
      "return_line_item_id": "retli_1kmn0aExample",
      "decision_basis": "explicit",
      "approved_quantity": 1,
      "return_required_quantity": 1,
      "allowed_resolution_types": ["refund"],
      "selected_resolution_type": "refund",
      "resolution_mode": "automatic",
      "refund_timing": "after_receipt",
      "is_inspection_required": false,
      "receiving_location_id": "loc_1kmn0aExample"
    }]
  }'

Skip decide when a policy already approved the return. On arrival, process the full handback quantity without resending the committed decision or completion mode:

cURL
curl -X POST https://api.withflintpay.com/v1/returns/ret_1kmn0aExample/process \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: mail-return-process-001" \
  -d '{
    "receipt": {
      "receiving_location_id": "loc_1kmn0aExample",
      "source_system": { "source_system_type": "manual" },
      "received_at": "2026-09-05T14:30:00Z"
    },
    "line_items": [{
      "return_line_item_id": "retli_1kmn0aExample",
      "received_quantity": 1,
      "resolution": { "resolution_type": "refund", "quantity": 1 }
    }]
  }'

Use the actual receipt time. If inspection is required, include an accepted inspection on each affected line in the process request. Use receiving and inspecting for partial receipts and separate inspection operations. Omitted dispositions follow the same pinned policy behavior as the counter flow.

Recover and reconcile#

Process requires Idempotency-Key. If its response is lost, replay the same key and body to recover the original result and child IDs without another stock or money effect. Reusing the key with a different body returns IDEMPOTENCY_KEY_REUSED. At a register, use the register transaction ID as the key: it is already unique, and you still have it when the HTTP response is lost. The decision, receipt, dispositions, inventory effects, and resolution intent commit together. Refund settlement can finish asynchronously.

Read GET /v1/returns/{return_id} and the returned receipt, disposition, and resolution IDs to reconcile progress. Follow return_resolution.updated and return.completed; a pending refund is not a reason to start another resolution.

For buyer-initiated returns, use self-serve returns.

Was this helpful?