> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reclack.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Customers

> Keep payments attached to a person rather than to an address.

A customer record is what turns a transfer into a relationship. Subscriptions,
invoices, payments and the portal all hang off it.

<Frame caption="Your own id is the join between your records and ours">
  <img className="block dark:hidden" src="https://mintcdn.com/reclack/hSqUHJp0KVXvwTsQ/images/customers.svg?fit=max&auto=format&n=hSqUHJp0KVXvwTsQ&q=85&s=3da2f7b38a6e507e2ca9451823184a51" alt="A row in your database beside the Reclack customer, joined by the external_id field." width="880" height="270" data-path="images/customers.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/reclack/hSqUHJp0KVXvwTsQ/images/customers-dark.svg?fit=max&auto=format&n=hSqUHJp0KVXvwTsQ&q=85&s=87fdb7ea2ce88a18fe2234380caa589c" alt="A row in your database beside the Reclack customer, joined by the external_id field." width="880" height="270" data-path="images/customers-dark.svg" />
</Frame>

## Creating one

```bash theme={null}
curl -X POST "https://api.reclack.com/v1/customers" \
  -H "Api-Key: $RECLACK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dana@acme.dev",
    "name": "Dana Okafor",
    "external_id": "user_4821",
    "metadata": { "plan": "pro", "signup_source": "docs" }
  }'
```

Only `email` is required. Everything else is there to make the record useful to
you later.

| Field | Why you want it |
| - | - |
| `external_id` | Your own identifier. Lets you find the customer without storing our id. |
| `name` | Shown on invoices and receipts. |
| `metadata` | Anything your systems need to carry along. Returned on the object. |

## Customers you did not create

A payer who completes a checkout or pays a payment link becomes a customer
automatically, matched on the email they gave or the wallet they paid from. You
do not have to create the record first.

This is why a payment link with no fields to fill in still produces a customer:
the wallet is the identity.

## Looking one up

```bash theme={null}
curl "https://api.reclack.com/v1/customers/cus_7Fh2PqX9" \
  -H "Api-Key: $RECLACK_KEY"
```

```json Response theme={null}
{
  "data": {
    "id": "cus_7Fh2PqX9",
    "email": "dana@acme.dev",
    "name": "Dana Okafor",
    "external_id": "user_4821",
    "metadata": { "plan": "pro" },
    "created_at": "2026-10-18T22:07:41Z",
    "updated_at": "2026-10-18T22:07:41Z"
  }
}
```

## Avoiding duplicates

Creating a customer is not idempotent, so a retried request can make a second
record. Guard it with your own identifier:

```js theme={null}
async function ensureCustomer(user) {
  const { data } = await reclack(`/v1/customers?external_id=${user.id}`);
  if (data.length > 0) return data[0];

  return reclack("/v1/customers", {
    method: "POST",
    body: { email: user.email, name: user.name, external_id: user.id },
  });
}
```

## What your customer sees

If you switch the [customer portal](/guides/customer-portal) on, this record is
what they sign into. They see their own plans, invoices, receipts and payments,
and nothing belonging to anybody else.

They sign in with the wallet they paid from, so there is no password to set and
nothing for your support team to reset.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.