Customers
Overview
A Customer is a reusable entity that groups a payer’s saved payment methods, payment history, and payment plans under a single identifier. Attaching customers to payment intents lets you:
- Charge saved payment methods without the customer present
- Link transactions to a payer for reporting and reconciliation
- Set up recurring payment plans via the API
All customer operations require a secret key (sk_xxx).
Create a customer
curl -X POST https://api.elasticpay.co/api/v1/customers \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "name": "Alice Smith", "email": "alice@example.com", "reference": "alice-user-42" }'const res = await fetch("https://api.elasticpay.co/api/v1/customers", { method: "POST", headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, body: JSON.stringify({ name: "Alice Smith", email: "alice@example.com", reference: "alice-user-42", }),});const customer = await res.json();import requests
res = requests.post( "https://api.elasticpay.co/api/v1/customers", headers={ "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, json={"name": "Alice Smith", "email": "alice@example.com", "reference": "alice-user-42"},)customer = 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/customers', [ 'json' => [ 'name' => 'Alice Smith', 'email' => 'alice@example.com', 'reference' => 'alice-user-42', ],]);$customer = 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/customers') do |req| req.body = { name: 'Alice Smith', email: 'alice@example.com', reference: 'alice-user-42' }endcustomer = 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 customer = await http.PostAsJsonAsync("/api/v1/customers", new { name = "Alice Smith", email = "alice@example.com", reference = "alice-user-42",});var result = await customer.Content.ReadFromJsonAsync<JsonElement>();Response
{ "id": "cus_0abc123def456ghi789jkl012mno", "name": "Alice Smith", "email": "alice@example.com", "reference": "alice-user-42", "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-04-01T10:00:00Z"}The id (e.g. cus_0abc...) is the customer’s stable identifier to use in subsequent requests.
The reference field is a freeform string you can use to correlate the customer with a record in your own system.
Fetch a customer
curl https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"const res = await fetch( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", { headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } });const customer = await res.json();import requests
res = requests.get( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", headers={"Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},)customer = 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/customers/cus_0abc123def456ghi789jkl012mno');$customer = 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/customers/cus_0abc123def456ghi789jkl012mno')customer = 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 customer = await http.GetFromJsonAsync<JsonElement>( "/api/v1/customers/cus_0abc123def456ghi789jkl012mno");List customers
curl "https://api.elasticpay.co/api/v1/customers?limit=20" \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"const res = await fetch( "https://api.elasticpay.co/api/v1/customers?limit=20", { headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } });const { data, has_more } = await res.json();import requests
res = requests.get( "https://api.elasticpay.co/api/v1/customers", headers={"Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}, params={"limit": 20},)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/customers', ['query' => ['limit' => 20]]);$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/customers') { |req| req.params['limit'] = 20 }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/customers?limit=20");Response shape
{ "data": [], "has_more": false}Supported query parameters:
| Parameter | Description |
|---|---|
limit | Number of results per page (default 20, max 100) |
starting_after | Cursor: return results after this customer ID |
email | Filter by email (exact match) |
reference | Filter by your external reference |
Update a customer
Use PUT to update any mutable field. Fields not included in the request body are left unchanged.
curl -X PUT https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{"email": "new-email@example.com"}'const res = await fetch( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", { method: "PUT", headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, body: JSON.stringify({ email: "new-email@example.com" }), });const updated = await res.json();import requests
res = requests.put( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", headers={ "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, json={"email": "new-email@example.com"},)updated = 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->put('/api/v1/customers/cus_0abc123def456ghi789jkl012mno', [ 'json' => ['email' => 'new-email@example.com'],]);$updated = 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.put('/api/v1/customers/cus_0abc123def456ghi789jkl012mno') do |req| req.body = { email: 'new-email@example.com' }endupdated = 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.PutAsJsonAsync( "/api/v1/customers/cus_0abc123def456ghi789jkl012mno", new { email = "new-email@example.com" });var updated = await res.Content.ReadFromJsonAsync<JsonElement>();Delete a customer
Deleting a customer performs a soft-delete — the record is hidden from API responses and the portal but retained in the database for audit purposes. Payment intents and transactions associated with the customer are preserved.
curl -X DELETE https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"await fetch( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", { method: "DELETE", headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, });import requests
requests.delete( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno", headers={"Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},)<?phpuse GuzzleHttp\Client;
$client = new Client([ 'base_uri' => 'https://api.elasticpay.co', 'headers' => [ 'Authorization' => 'Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'Content-Type' => 'application/json', ],]);
$client->delete('/api/v1/customers/cus_0abc123def456ghi789jkl012mno');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'
conn.delete('/api/v1/customers/cus_0abc123def456ghi789jkl012mno')using 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");
await http.DeleteAsync("/api/v1/customers/cus_0abc123def456ghi789jkl012mno");A successful deletion returns 204 No Content.
List a customer’s payment methods
Retrieve all saved payment methods (pm_xxx) for a customer:
curl https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno/payment_methods \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"const res = await fetch( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno/payment_methods", { headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } });const { data } = await res.json();import requests
res = requests.get( "https://api.elasticpay.co/api/v1/customers/cus_0abc123def456ghi789jkl012mno/payment_methods", headers={"Authorization": "Bearer sk_sandbox_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/customers/cus_0abc123def456ghi789jkl012mno/payment_methods');$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/customers/cus_0abc123def456ghi789jkl012mno/payment_methods')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/customers/cus_0abc123def456ghi789jkl012mno/payment_methods");Attach a customer to a payment intent
Pass customer_id when creating a payment intent to associate it with a customer:
curl -X POST https://api.elasticpay.co/api/v1/payment_intents \ -H "Authorization: Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "amount": 4900, "currency": "AUD", "customer_id": "cus_0abc123def456ghi789jkl012mno" }'const res = await fetch("https://api.elasticpay.co/api/v1/payment_intents", { method: "POST", headers: { "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, body: JSON.stringify({ amount: 4900, currency: "AUD", customer_id: "cus_0abc123def456ghi789jkl012mno", }),});const pi = await res.json();import requests
res = requests.post( "https://api.elasticpay.co/api/v1/payment_intents", headers={ "Authorization": "Bearer sk_sandbox_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Content-Type": "application/json", }, json={"amount": 4900, "currency": "AUD", "customer_id": "cus_0abc123def456ghi789jkl012mno"},)pi = 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', [ 'json' => [ 'amount' => 4900, 'currency' => 'AUD', 'customer_id' => 'cus_0abc123def456ghi789jkl012mno', ],]);$pi = 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') do |req| req.body = { amount: 4900, currency: 'AUD', customer_id: 'cus_0abc123def456ghi789jkl012mno' }endpi = 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", new { amount = 4900, currency = "AUD", customer_id = "cus_0abc123def456ghi789jkl012mno",});var pi = await res.Content.ReadFromJsonAsync<JsonElement>();Required permissions
| Operation | Required scope |
|---|---|
| Create / update / delete | customers:write |
| Fetch / list | customers:read |
Secret keys (sk_xxx) have both scopes by default.