# Create or reuse a customer

`POST /api/v1/customers`

Adds a customer to the register, keyed on email. An email that already exists answers 200 with the existing customer instead of creating a second one, so this is safe to call on every sync. Requires the "customers:write" scope. An "Idempotency-Key" header is optional — the endpoint is already idempotent on the email — but is honoured when sent.

Scope: `customers:write`
Idempotency-Key: optional

## Parameters

- `Idempotency-Key` (header, string) — Optional. A unique key, 8-200 characters. Retrying with the same key replays the first response verbatim instead of acting twice.

## Request body

- `email` (string, required) — The customer's email. This is the identity: posting an email that already exists returns 200 with the existing customer instead of creating a second one.
- `name` (string, required) — The customer's name.
- `phone` (string) — The customer's phone number.
- `email_subscription` (boolean) — Whether the customer has agreed to marketing email. Defaults to false — consent is something you record, never something we assume.

## Responses

- `200` — The customer. 201 when it was created, 200 when it already existed. Returned when nothing new was created — the resource already existed, or this is a replay of an earlier request with the same Idempotency-Key.
- `201` — The customer. 201 when it was created, 200 when it already existed.
- `400` — Invalid request — codes "validation_failed" or, on an endpoint that requires one, "idempotency_key_required".
- `401` — Missing, invalid, revoked or expired API key — codes "api_key_missing", "api_key_invalid", "api_key_revoked", "api_key_expired".
- `403` — The API app is off, the plan does not include the API, or the key lacks the required scope — codes "app_not_enabled", "plan_upgrade_required", "insufficient_scope" (the last carries "required_scope").
- `422` — The request was understood but cannot be fulfilled as asked — codes "validation_failed" or "idempotency_key_reused" (the same Idempotency-Key was already used with a different body).
- `429` — Rate limit exceeded — code "rate_limited". See the x-ratelimit-* headers.
- `500` — Something went wrong on our side — code "internal_error".

## Response `200`

- `id` (string, required) — Awrora id (UUID) for the customer record.
- `name` (string, required) — Customer name.
- `email` (string, required) — Customer email. Unique within the organization.
- `phone` (string | null, required) — Phone number, or null.
- `tags` (string[], required) — Merchant-defined tags. May be empty.
- `email_subscription` (boolean, required) — True when the customer has opted in to marketing email.
- `created_at` (string, required) — ISO 8601 timestamp with offset.

## Example

```bash
curl -X POST "https://your-site.awrora.app/api/v1/customers" \
  -H "Authorization: Bearer $AWRORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "anna@example.com",
  "name": "string",
  "phone": "string",
  "email_subscription": false
}'
```