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

# Create a contact

> POST /v1/contacts — add a contact to the project's address book with optional name, subscription state, and metadata.

Add a person to the project's address book. Contacts carry name, subscription state, and arbitrary metadata you can use in templates and reporting.

**`POST /v1/contacts`**

## Body

<ParamField body="email" type="string" required>
  The contact's email address. Unique within the project.
</ParamField>

<ParamField body="firstName" type="string">
  Given name.
</ParamField>

<ParamField body="lastName" type="string">
  Family name.
</ParamField>

<ParamField body="subscribed" type="boolean">
  Whether the contact is opted in. Defaults to `true`. When `false`, `unsubscribedAt` is stamped on create.
</ParamField>

<ParamField body="metadata" type="object">
  Free-form key/value pairs stored alongside the contact.
</ParamField>

<Note>
  **Subscription is not suppression.** The `subscribed` flag is an app-level marketing signal. It does not block delivery — that's the job of [suppressions](/api-reference/suppressions/list). A complaint still drops a message even if `subscribed` is `true`.
</Note>

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.drin.run/v1/contacts \
    -H "Authorization: Bearer $DRIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "email": "ada@example.com",
      "firstName": "Ada",
      "lastName": "Lovelace",
      "metadata": { "plan": "pro" }
    }'
  ```

  ```typescript Node.js theme={null}
  import { DrinClient } from "@drin00/sdk";

  const drin = new DrinClient({ apiKey: process.env.DRIN_API_KEY });

  const contact = await drin.contacts.create({
    email: "ada@example.com",
    firstName: "Ada",
    lastName: "Lovelace",
    metadata: { plan: "pro" },
  });
  ```
</CodeGroup>

## Response

Returns `201 Created` with the contact. If a contact with the same email already exists in this project, the call returns `409 conflict` (`contact_email_taken`).

```json 201 Created theme={null}
{
  "id": "ct_7Yh2Lp",
  "email": "ada@example.com",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "subscribed": true,
  "unsubscribedAt": null,
  "metadata": { "plan": "pro" },
  "createdAt": "2026-06-02T17:30:00.000Z",
  "updatedAt": "2026-06-02T17:30:00.000Z"
}
```
