Refunds
Refunds are vendor-initiated and non-custodial. The vendor signs and broadcasts the refund transaction directly from their wallet to the consumer's wallet. APISettle tracks and validates the refund but never holds the funds.
How refunds work
- 1 Create intent — Vendor calls
POST /refundswith the settlement ID and refund amount. - 2 Sign and broadcast — Vendor signs a Solana transfer from their wallet to the consumer's wallet and broadcasts it.
- 3 Submit tx hash — Vendor submits the transaction hash to APISettle. The platform validates and records the refund.
Create a refund intent
POST /v1/refunds
Creates a refund intent tied to a specific settlement. You can refund the full amount or a partial amount. APISettle validates that the cumulative refund doesn't exceed the original payment.
// Create a refund intent for a settled payment
const res = await fetch('https://api.apisettle.com/v1/refunds', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
settlement_id: 'stl_abc123',
amount: '2000000', // $2.00 — full or partial
reason: 'Customer requested cancellation',
}),
})
const refund = await res.json()
// {
// id: "ref_...",
// settlement_id: "stl_abc123",
// amount: "2000000",
// currency: "USDC",
// status: "pending_vendor_submit"
// } Refund parameters
| Field | Type | Description |
|---|---|---|
| settlement_id | string | The settlement to refund. Must be redeemed. |
| amount | string | Refund amount in USDC micro-units. Must be positive. |
| reason | string? | Optional reason (max 500 characters). |
Submit the refund transaction
POST /v1/refunds/:id/submit
After broadcasting the refund transfer on Solana, submit the transaction hash so APISettle can validate and record the refund.
// After signing and broadcasting the refund tx on-chain,
// submit the tx hash to APISettle for confirmation
const res = await fetch(
`https://api.apisettle.com/v1/refunds/${refundId}/submit`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
refund_tx_hash: '5UzH3nPjK...',
}),
},
)
const result = await res.json()
// { id: "ref_...", status: "confirmed", confirmed_at: "..." } Refund lifecycle
| Status | Meaning |
|---|---|
| pending_vendor_submit | Intent created. Awaiting vendor's on-chain tx. |
| submitted | Tx hash submitted. Awaiting on-chain confirmation. |
| confirmed | Refund confirmed on-chain. Consumer received funds. |
| failed | On-chain tx failed or validation error. |
| cancelled | Vendor cancelled before submitting tx. |
| expired | Vendor didn't submit tx within the allowed window. |
Partial refunds
You can issue multiple partial refunds against the same settlement. APISettle tracks the cumulative refunded amount and rejects any refund that would exceed the original payment.
Example: A $10.00 settlement can be refunded as $3.00 + $4.00 + $3.00 (three separate refunds totaling $10.00). A fourth refund of any amount would be rejected.
Other refund operations
| Action | Endpoint |
|---|---|
| Cancel a pending refund | POST /refunds/:id/cancel |
| Get refund details | GET /refunds/:id |
| List all refunds | GET /refunds |