A Customer (cus_...) is a buyer your store keeps on file: an email, a name, a phone, addresses, your own metadata and up to five tax IDs. Create one for a buyer you expect to see again. You can then name it in customer on a PaymentIntent, list the cards saved to it, and look it up by email or by search. A one-off payment does not need a Customer.
This page walks one Customer from create to delete. Every request below runs on a fresh test store in the order shown, and each id comes from an earlier answer. The full list of fields is in the Customers API reference.
Create a Customer#
Send what you know about the buyer. Every field is optional. To store tax IDs at the same time, add tax_id_data entries, numbered from 0, each with a type and a value. Make one Idempotency-Key for each Customer you mean to create: a retry with that key answers the same Customer instead of a second one.
curl https://api.fluveo.com/v1/customers \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: crm-a1042-create" \
-d email=ada@example.com \
-d name="Ada Lovelace" \
-d "metadata[crm_id]=A-1042" \
-d "tax_id_data[0][type]=br_cpf" \
-d "tax_id_data[0][value]=52998224725"const response = await fetch("https://api.fluveo.com/v1/customers", {
method: "POST",
headers: {
Authorization: "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-create",
},
body: new URLSearchParams({
email: "ada@example.com",
name: "Ada Lovelace",
"metadata[crm_id]": "A-1042",
"tax_id_data[0][type]": "br_cpf",
"tax_id_data[0][value]": "52998224725",
}),
});
const customer = await response.json();
console.log(customer.id);import requests
response = requests.post(
"https://api.fluveo.com/v1/customers",
headers={
"Authorization": "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-create",
},
data={
"email": "ada@example.com",
"name": "Ada Lovelace",
"metadata[crm_id]": "A-1042",
"tax_id_data[0][type]": "br_cpf",
"tax_id_data[0][value]": "52998224725",
},
)
customer = response.json()
print(customer["id"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer sk_test_...",
"Idempotency-Key: crm-a1042-create",
],
CURLOPT_POSTFIELDS => http_build_query([
"email" => "ada@example.com",
"name" => "Ada Lovelace",
"metadata" => ["crm_id" => "A-1042"],
"tax_id_data" => [["type" => "br_cpf", "value" => "52998224725"]],
]),
]);
$customer = json_decode(curl_exec($ch), true);
echo $customer["id"];The answer is the new Customer. Keep its id: every later call on this page uses it.
{
"id": "cus_...",
"object": "customer",
"email": "ada@example.com",
"name": "Ada Lovelace",
"phone": null,
"description": null,
"metadata": { "crm_id": "A-1042" },
"tax_exempt": "none",
"preferred_locales": [],
"created": 1762862400,
"livemode": false
}The tax IDs are kept, but a Customer shows its tax_ids list only when you ask for it with expand[]=tax_ids (see Expanding responses).
Retrieve a Customer#
GET /v1/customers/{customer} reads one Customer. Here it also expands tax_ids, so you can see the CPF stored by the create.
curl -G https://api.fluveo.com/v1/customers/cus_... \
-H "Authorization: Bearer sk_test_..." \
-d "expand[]=tax_ids"const response = await fetch("https://api.fluveo.com/v1/customers/cus_...?expand[]=tax_ids", {
headers: { Authorization: "Bearer sk_test_..." },
});
const customer = await response.json();
console.log(customer.tax_ids.data);import requests
response = requests.get(
"https://api.fluveo.com/v1/customers/cus_...",
headers={"Authorization": "Bearer sk_test_..."},
params={"expand[]": "tax_ids"},
)
customer = response.json()
print(customer["tax_ids"]["data"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_...?expand[]=tax_ids");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$customer = json_decode(curl_exec($ch), true);
print_r($customer["tax_ids"]["data"]);Fluveo stores a tax ID in the usual written form of its type, so the digits 52998224725 come back as 529.982.247-25.
{
"id": "cus_...",
"object": "customer",
"email": "ada@example.com",
"tax_ids": {
"object": "list",
"data": [
{
"id": "txi_...",
"object": "tax_id",
"type": "br_cpf",
"value": "529.982.247-25",
"customer": "cus_..."
}
],
"has_more": false,
"url": "/v1/customers/cus_.../tax_ids"
}
}Update a Customer#
POST /v1/customers/{customer} changes only the fields you send and leaves the rest as they were. metadata merges key by key: a new key is added, and a key sent with an empty value is removed. Tax IDs are not changed here: use the tax ID calls below.
curl https://api.fluveo.com/v1/customers/cus_... \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: crm-a1042-update-1" \
-d description="Wholesale buyer" \
-d "metadata[segment]=wholesale"const response = await fetch("https://api.fluveo.com/v1/customers/cus_...", {
method: "POST",
headers: {
Authorization: "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-update-1",
},
body: new URLSearchParams({
description: "Wholesale buyer",
"metadata[segment]": "wholesale",
}),
});
const customer = await response.json();
console.log(customer.description, customer.metadata);import requests
response = requests.post(
"https://api.fluveo.com/v1/customers/cus_...",
headers={
"Authorization": "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-update-1",
},
data={
"description": "Wholesale buyer",
"metadata[segment]": "wholesale",
},
)
customer = response.json()
print(customer["description"], customer["metadata"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_...");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer sk_test_...",
"Idempotency-Key: crm-a1042-update-1",
],
CURLOPT_POSTFIELDS => http_build_query([
"description" => "Wholesale buyer",
"metadata" => ["segment" => "wholesale"],
]),
]);
$customer = json_decode(curl_exec($ch), true);
echo $customer["description"];The Customer comes back with the new description and both metadata keys.
{
"id": "cus_...",
"object": "customer",
"description": "Wholesale buyer",
"metadata": { "crm_id": "A-1042", "segment": "wholesale" }
}Find Customers#
List by email#
GET /v1/customers lists your Customers, newest first, paged with limit (1 to 100, default 10), starting_after and ending_before (see Pagination). email narrows the list to one exact address. The match is case-sensitive: Ada@example.com does not find ada@example.com. created filters on the creation time.
curl -G https://api.fluveo.com/v1/customers \
-H "Authorization: Bearer sk_test_..." \
-d email=ada@example.com \
-d limit=3const query = new URLSearchParams({ email: "ada@example.com", limit: "3" });
const response = await fetch("https://api.fluveo.com/v1/customers?" + query, {
headers: { Authorization: "Bearer sk_test_..." },
});
const list = await response.json();
console.log(list.data.length, list.has_more);import requests
response = requests.get(
"https://api.fluveo.com/v1/customers",
headers={"Authorization": "Bearer sk_test_..."},
params={"email": "ada@example.com", "limit": 3},
)
page = response.json()
print(len(page["data"]), page["has_more"])<?php
$query = http_build_query(["email" => "ada@example.com", "limit" => 3]);
$ch = curl_init("https://api.fluveo.com/v1/customers?" . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$list = json_decode(curl_exec($ch), true);
echo count($list["data"]);{
"object": "list",
"data": [{ "id": "cus_...", "object": "customer", "email": "ada@example.com" }],
"has_more": false,
"url": "/v1/customers"
}Search#
GET /v1/customers/search takes a query and answers a search_result with data, has_more and next_page. A Customer can be found as soon as the write that made it returns.
curl -G https://api.fluveo.com/v1/customers/search \
-H "Authorization: Bearer sk_test_..." \
--data-urlencode 'query=email:"ada@example.com"'const query = new URLSearchParams({ query: 'email:"ada@example.com"' });
const response = await fetch("https://api.fluveo.com/v1/customers/search?" + query, {
headers: { Authorization: "Bearer sk_test_..." },
});
const result = await response.json();
console.log(result.data.length);import requests
response = requests.get(
"https://api.fluveo.com/v1/customers/search",
headers={"Authorization": "Bearer sk_test_..."},
params={"query": 'email:"ada@example.com"'},
)
result = response.json()
print(len(result["data"]))<?php
$query = http_build_query(["query" => 'email:"ada@example.com"']);
$ch = curl_init("https://api.fluveo.com/v1/customers/search?" . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$result = json_decode(curl_exec($ch), true);
echo count($result["data"]);{
"object": "search_result",
"url": "/v1/customers/search",
"data": [{ "id": "cus_...", "object": "customer", "email": "ada@example.com" }],
"has_more": false,
"next_page": null
}A query is made of clauses: a field, an operator and a value in quotes. The fields are email, name, phone, created and metadata["key"].
| Query | Finds |
|---|---|
email:"ada@example.com" | that address, in any letter case |
name:"ada lovelace" | names holding those whole words, in that order, in any case |
name~"love" | names holding "love" anywhere; a ~ value needs at least 3 characters, and a shorter one finds nothing |
metadata["crm_id"]:"A-1042" | Customers whose crm_id metadata is A-1042 |
created>1762000000 | Customers made after that Unix time; created takes =, :, >, >=, < and <= with a whole number |
-phone:null | Customers that have a phone; a - negates a clause |
email:"a@example.com" OR email:"b@example.com" | either address |
Join up to 10 clauses with AND or with OR, never both in one query, and without parentheses. A space between clauses counts as AND. When has_more is true, send next_page back as page, with the same query, to read the next page. Add expand[]=total_count to get total_count, the number of matches. A deleted Customer is never found.
Tax IDs#
A Customer holds up to five tax IDs (txi_...). Each has a type and a value. The type is br_cpf for a CPF or br_cnpj for a CNPJ. Send the value with or without its dots, dash and slash: Fluveo checks that it has the form of its type and answers it in that written form. Add tax IDs with tax_id_data when you create the Customer, or one at a time with the calls below. A tax ID cannot be edited: delete it and add the new one.
Add a tax ID#
curl https://api.fluveo.com/v1/customers/cus_.../tax_ids \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: crm-a1042-cnpj" \
-d type=br_cnpj \
-d value=11222333000181const response = await fetch("https://api.fluveo.com/v1/customers/cus_.../tax_ids", {
method: "POST",
headers: {
Authorization: "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-cnpj",
},
body: new URLSearchParams({ type: "br_cnpj", value: "11222333000181" }),
});
const taxId = await response.json();
console.log(taxId.id, taxId.value);import requests
response = requests.post(
"https://api.fluveo.com/v1/customers/cus_.../tax_ids",
headers={
"Authorization": "Bearer sk_test_...",
"Idempotency-Key": "crm-a1042-cnpj",
},
data={"type": "br_cnpj", "value": "11222333000181"},
)
tax_id = response.json()
print(tax_id["id"], tax_id["value"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_.../tax_ids");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer sk_test_...",
"Idempotency-Key: crm-a1042-cnpj",
],
CURLOPT_POSTFIELDS => http_build_query(["type" => "br_cnpj", "value" => "11222333000181"]),
]);
$taxId = json_decode(curl_exec($ch), true);
echo $taxId["id"];The answer is the new tax ID. Keep its id for the calls below.
{
"id": "txi_...",
"object": "tax_id",
"type": "br_cnpj",
"value": "11.222.333/0001-81",
"customer": "cus_...",
"created": 1762862460,
"livemode": false
}List a Customer's tax IDs#
GET /v1/customers/{customer}/tax_ids answers them oldest first, paged with limit, starting_after and ending_before. This Customer now has two: the CPF from the create and the CNPJ.
curl https://api.fluveo.com/v1/customers/cus_.../tax_ids \
-H "Authorization: Bearer sk_test_..."const response = await fetch("https://api.fluveo.com/v1/customers/cus_.../tax_ids", {
headers: { Authorization: "Bearer sk_test_..." },
});
const list = await response.json();
console.log(list.data.map((taxId) => taxId.type));import requests
response = requests.get(
"https://api.fluveo.com/v1/customers/cus_.../tax_ids",
headers={"Authorization": "Bearer sk_test_..."},
)
print([tax_id["type"] for tax_id in response.json()["data"]])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_.../tax_ids");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$list = json_decode(curl_exec($ch), true);
echo count($list["data"]);{
"object": "list",
"data": [
{ "id": "txi_...", "object": "tax_id", "type": "br_cpf", "value": "529.982.247-25" },
{ "id": "txi_...", "object": "tax_id", "type": "br_cnpj", "value": "11.222.333/0001-81" }
],
"has_more": false,
"url": "/v1/customers/cus_.../tax_ids"
}Retrieve a tax ID#
curl https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_... \
-H "Authorization: Bearer sk_test_..."const response = await fetch("https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...", {
headers: { Authorization: "Bearer sk_test_..." },
});
const taxId = await response.json();
console.log(taxId.value);import requests
response = requests.get(
"https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...",
headers={"Authorization": "Bearer sk_test_..."},
)
print(response.json()["value"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$taxId = json_decode(curl_exec($ch), true);
echo $taxId["value"];The answer is the same tax ID object the create returned.
Delete a tax ID#
curl -X DELETE https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_... \
-H "Authorization: Bearer sk_test_..."const response = await fetch("https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...", {
method: "DELETE",
headers: { Authorization: "Bearer sk_test_..." },
});
const deleted = await response.json();
console.log(deleted.deleted);import requests
response = requests.delete(
"https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...",
headers={"Authorization": "Bearer sk_test_..."},
)
print(response.json()["deleted"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_.../tax_ids/txi_...");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$deleted = json_decode(curl_exec($ch), true);
var_dump($deleted["deleted"]);{
"id": "txi_...",
"object": "tax_id",
"deleted": true
}The tax ID leaves the Customer's list at once, and its id then answers 404 resource_missing.
Use a Customer in a payment#
Name it on a PaymentIntent#
Send the Customer's id in customer when you create a PaymentIntent. The payment is then tied to that buyer, and the PaymentIntent and its charge answer that customer. The amount is in the currency's smallest unit: 2000 is $20.00. This request only creates the PaymentIntent; to confirm and pay it, see Accept a payment.
curl https://api.fluveo.com/v1/payment_intents \
-H "Authorization: Bearer sk_test_..." \
-H "Idempotency-Key: order-2077-pay" \
-d amount=2000 \
-d currency=usd \
-d "payment_method_types[]=card" \
-d customer=cus_...const response = await fetch("https://api.fluveo.com/v1/payment_intents", {
method: "POST",
headers: {
Authorization: "Bearer sk_test_...",
"Idempotency-Key": "order-2077-pay",
},
body: new URLSearchParams({
amount: "2000",
currency: "usd",
"payment_method_types[]": "card",
customer: "cus_...",
}),
});
const paymentIntent = await response.json();
console.log(paymentIntent.id, paymentIntent.customer);import requests
response = requests.post(
"https://api.fluveo.com/v1/payment_intents",
headers={
"Authorization": "Bearer sk_test_...",
"Idempotency-Key": "order-2077-pay",
},
data={
"amount": 2000,
"currency": "usd",
"payment_method_types[]": "card",
"customer": "cus_...",
},
)
payment_intent = response.json()
print(payment_intent["id"], payment_intent["customer"])<?php
$ch = curl_init("https://api.fluveo.com/v1/payment_intents");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer sk_test_...",
"Idempotency-Key: order-2077-pay",
],
CURLOPT_POSTFIELDS => http_build_query([
"amount" => 2000,
"currency" => "usd",
"payment_method_types" => ["card"],
"customer" => "cus_...",
]),
]);
$paymentIntent = json_decode(curl_exec($ch), true);
echo $paymentIntent["customer"];{
"id": "pi_...",
"object": "payment_intent",
"amount": 2000,
"currency": "usd",
"customer": "cus_...",
"status": "requires_payment_method"
}GET /v1/payment_intents takes customer too, to list one buyer's payments. See the customer parameter in the reference.
List its saved cards#
GET /v1/customers/{customer}/payment_methods lists the PaymentMethods saved to a Customer. Narrow it with type=card, and page it with limit, starting_after and ending_before. A new Customer has none, so this list is empty until a card is saved to it.
curl -G https://api.fluveo.com/v1/customers/cus_.../payment_methods \
-H "Authorization: Bearer sk_test_..." \
-d type=cardconst response = await fetch("https://api.fluveo.com/v1/customers/cus_.../payment_methods?type=card", {
headers: { Authorization: "Bearer sk_test_..." },
});
const list = await response.json();
console.log(list.data.length);import requests
response = requests.get(
"https://api.fluveo.com/v1/customers/cus_.../payment_methods",
headers={"Authorization": "Bearer sk_test_..."},
params={"type": "card"},
)
print(len(response.json()["data"]))<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_.../payment_methods?type=card");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$list = json_decode(curl_exec($ch), true);
echo count($list["data"]);{
"object": "list",
"data": [],
"has_more": false,
"url": "/v1/customers/cus_.../payment_methods"
}GET /v1/customers/{customer}/payment_methods/{payment_method} reads one card through its Customer.
Delete a Customer#
DELETE /v1/customers/{customer} deletes a Customer for good. There is no undo.
curl -X DELETE https://api.fluveo.com/v1/customers/cus_... \
-H "Authorization: Bearer sk_test_..."const response = await fetch("https://api.fluveo.com/v1/customers/cus_...", {
method: "DELETE",
headers: { Authorization: "Bearer sk_test_..." },
});
const deleted = await response.json();
console.log(deleted.deleted);import requests
response = requests.delete(
"https://api.fluveo.com/v1/customers/cus_...",
headers={"Authorization": "Bearer sk_test_..."},
)
print(response.json()["deleted"])<?php
$ch = curl_init("https://api.fluveo.com/v1/customers/cus_...");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$deleted = json_decode(curl_exec($ch), true);
var_dump($deleted["deleted"]);{
"id": "cus_...",
"object": "customer",
"deleted": true
}What changes after a delete:
- Reading it.
GET /v1/customers/{customer}still answers 200, with onlyid,objectand"deleted": true. The list and the search leave the Customer out. An update answers 404resource_missing. - Its saved cards. They are not detached: each keeps
customerset to the deleted id, and nopayment_method.detachedevent is sent. They can no longer pay. Confirming a PaymentIntent that holds one is refused with 400payment_method_unexpected_state, and no charge is made. You can still detach a card withPOST /v1/payment_methods/{payment_method}/detach. - Open PaymentIntents. A PaymentIntent that names the deleted Customer and is not paid yet cannot be confirmed: the confirm is refused with
resource_missingoncustomer, and no charge is made. A new PaymentIntent that names the deleted Customer is refused the same way. - Past payments. The delete changes only the Customer. PaymentIntents, charges and refunds made before it stay as they were, with their
customerid. - Events. Only
customer.deletedis sent.
Parameters#
Customer fields#
POST /v1/customers takes all of these. POST /v1/customers/{customer} takes all but tax_id_data.
The buyer's email address. It must look like an address, and it is stored as sent.
The person's or the company's name. Leading and trailing spaces are dropped.
The buyer's phone number, trimmed like
name.Your own note about this buyer.
The buyer's address.
Where to ship orders. When you send
shipping, it needs anameand anaddress.Up to 50 of your own key-value pairs, sent as
metadata[key]=value. On an update, an empty value removes its key. See Metadata.The buyer's languages, most preferred first, as
preferred_locales[]=pt-BR. Sendpreferred_locales=to empty the list.none(the default),exemptorreverse. Fluveo stores and shows it, and an empty value sets it back tonone.Create only. Tax IDs made with the Customer, as
tax_id_data[0][type]andtax_id_data[0][value], then[1]and so on, up to five.
Tax ID fields#
br_cpffor a CPF,br_cnpjfor a CNPJ.The number, with or without its punctuation. It is answered in the written form of its type.
States and events#
A Customer has no status field. It exists until you delete it, and then reads back as deleted.
| Event | When |
|---|---|
customer.created | A Customer was created. A create with tax_id_data first sends one customer.tax_id.created per tax ID, then this event. |
customer.updated | An update changed the Customer. data.previous_attributes holds the old values. |
customer.deleted | The Customer was deleted. It is the only event a delete sends. |
customer.tax_id.created | A tax ID was added, at create or with POST /v1/customers/{customer}/tax_ids. |
customer.tax_id.deleted | A tax ID was deleted. |
customer.tax_id.updated | A tax ID's verification check finished. A br_cpf or br_cnpj tax ID goes through no such check, so it never sends this event. |
Errors you may see#
| Error | Why |
|---|---|
400 email_invalid | The email is not an email address. No Customer is created. |
400 parameter_missing | shipping was sent without its name, or without its address. |
400 parameter_unknown | A parameter this call does not take, such as balance or tax. |
400 tax_id_invalid | The value does not have the form of its type, such as a CPF with too few digits. |
400 resource_already_exists | The Customer already has a tax ID with this type and value. |
| 400 "Customer cus_... already has the maximum 5 tax IDs attached." | The Customer has five tax IDs: delete one first. |
404 resource_missing | The cus_... or txi_... is not one of your store's, or the Customer was deleted (on update). |
400 payment_method_unexpected_state | The PaymentIntent holds a card of a deleted Customer. Confirm it with another payment method. |
See Errors for the shape of every error.
Test it#
- Create a Customer with
email,nameandtax_id_data[0][type]=br_cpfwithtax_id_data[0][value]=52998224725: you get acus_..., onecustomer.tax_id.createdand thencustomer.created. - Retrieve it with
expand[]=tax_ids: the list holds the CPF as529.982.247-25. - Update its
description: the answer shows the new value, andcustomer.updatedcarries the old one inprevious_attributes. - List with
email=and the same address: the Customer is there. List with the address in capitals: the list is empty. Search withemail:"...": it is found. - Add a
br_cnpjtax ID: you get atxi_.... Add the same one again: 400resource_already_exists. Addtype=br_cpfwithvalue=123: 400tax_id_invalid. - Delete the CNPJ:
"deleted": true, andcustomer.tax_id.deletedarrives. - Create a PaymentIntent with
customer=cus_...: it answers thatcustomer. List the Customer's cards: the list is empty. - Delete the Customer:
"deleted": trueandcustomer.deleted. Retrieve it: 200 with"deleted": true. Search for it: no match. Confirm the PaymentIntent of step 7 withpayment_method=pm_card_visa: it is refused withresource_missingoncustomer.
Next#
customer.* event carries.MetadataStore your own keys on a Customer.