Refunds
Full refund
To refund the full payment amount, POST to the refunds endpoint with no amount_cents field:
curl -X POST https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"reason": "customer_request"}'const res = await fetch( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", { method: "POST", headers: { "Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, body: JSON.stringify({ reason: "customer_request" }), });const refund = await res.json();import requests
res = requests.post( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", headers={ "Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, json={"reason": "customer_request"},)refund = res.json()<?phpuse GuzzleHttp\Client;
$client = new Client([ 'base_uri' => 'https://api.elasticpay.co', 'headers' => [ 'Authorization' => 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type' => 'application/json', ],]);
$res = $client->post( '/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds', ['json' => ['reason' => 'customer_request']]);$refund = json_decode($res->getBody(), true);require 'faraday'require 'json'
conn = Faraday.new('https://api.elasticpay.co') do |f| f.request :json f.response :jsonendconn.headers['Authorization'] = 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'conn.headers['Content-Type'] = 'application/json'
res = conn.post('/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds') do |req| req.body = { reason: 'customer_request' }endrefund = res.bodyusing System.Net.Http;using System.Net.Http.Headers;using System.Net.Http.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://api.elasticpay.co") };http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var res = await http.PostAsJsonAsync( "/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", new { reason = "customer_request" });var refund = await res.Content.ReadFromJsonAsync<JsonElement>();Response
{ "success": true, "status": "succeeded", "transaction_id": "pi_0abc123def456ghi789jkl012mn", "refund_id": "re_0abc123def456", "message": "Full refund of 5000 AUD processed", "amount_cents": 5000, "currency": "AUD"}Partial refund
Specify amount_cents to refund a portion of the payment. Multiple partial refunds are allowed as long as the total does not exceed the original charged amount.
curl -X POST https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"amount_cents": 2000, "reason": "partial_return"}'const res = await fetch( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", { method: "POST", headers: { "Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, body: JSON.stringify({ amount_cents: 2000, reason: "partial_return" }), });const refund = await res.json();import requests
res = requests.post( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", headers={ "Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, json={"amount_cents": 2000, "reason": "partial_return"},)refund = res.json()<?phpuse GuzzleHttp\Client;
$client = new Client([ 'base_uri' => 'https://api.elasticpay.co', 'headers' => [ 'Authorization' => 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type' => 'application/json', ],]);
$res = $client->post( '/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds', ['json' => ['amount_cents' => 2000, 'reason' => 'partial_return']]);$refund = json_decode($res->getBody(), true);require 'faraday'require 'json'
conn = Faraday.new('https://api.elasticpay.co') do |f| f.request :json f.response :jsonendconn.headers['Authorization'] = 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'conn.headers['Content-Type'] = 'application/json'
res = conn.post('/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds') do |req| req.body = { amount_cents: 2000, reason: 'partial_return' }endrefund = res.bodyusing System.Net.Http;using System.Net.Http.Headers;using System.Net.Http.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://api.elasticpay.co") };http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var res = await http.PostAsJsonAsync( "/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", new { amount_cents = 2000, reason = "partial_return" });var refund = await res.Content.ReadFromJsonAsync<JsonElement>();Response
{ "success": true, "status": "succeeded", "transaction_id": "pi_0abc123def456ghi789jkl012mn", "refund_id": "re_0def456ghi789", "message": "Partial refund of 2000 AUD processed", "amount_cents": 2000, "currency": "AUD"}List refunds
Retrieve all refunds for a payment intent:
curl https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds \ -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"const res = await fetch( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", { headers: { "Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } });const data = await res.json();import requests
res = requests.get( "https://api.elasticpay.co/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds", headers={"Authorization": "Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},)data = res.json()<?phpuse GuzzleHttp\Client;
$client = new Client([ 'base_uri' => 'https://api.elasticpay.co', 'headers' => [ 'Authorization' => 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type' => 'application/json', ],]);
$res = $client->get('/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds');$data = json_decode($res->getBody(), true);require 'faraday'require 'json'
conn = Faraday.new('https://api.elasticpay.co') do |f| f.request :json f.response :jsonendconn.headers['Authorization'] = 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'conn.headers['Content-Type'] = 'application/json'
res = conn.get('/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds')data = res.bodyusing System.Net.Http;using System.Net.Http.Headers;using System.Net.Http.Json;
using var http = new HttpClient { BaseAddress = new Uri("https://api.elasticpay.co") };http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var data = await http.GetFromJsonAsync<JsonElement>( "/api/v1/payment_intents/pi_0abc123def456ghi789jkl012mn/refunds");Request fields
| Field | Type | Required | Description |
|---|---|---|---|
amount_cents | integer | No | Amount to refund in the smallest currency unit. Omit for a full refund. |
reason | string | No | One of customer_request, duplicate, fraudulent. Passed to the PSP. |
Refund statuses
| Status | Meaning |
|---|---|
succeeded | Refund confirmed by PSP |
pending | Submitted to PSP, awaiting confirmation |
failed | PSP rejected the refund |
Constraints
- The payment intent must be in
succeededstatus - Total refund amount across all refunds cannot exceed the original charged amount
- A full refund transitions the payment intent status to
refunded - A partial refund keeps the payment intent in
succeeded - A failed refund does not affect the payment intent status — retry with a new request
Webhook events
| Event | When |
|---|---|
payment_intent.refunded | All charged funds have been refunded |
payment_intent.partially_refunded | A partial refund succeeded (remaining balance > 0) |
payment_intent.refund_failed | Refund attempt failed |
See Webhooks for how to handle these events.