---
title: "Create or update a contact"
method: POST
path: "/contacts"
tags: ["Contacts"]
---

# Create or update a contact

`POST /contacts`

## Request

- Base URL: `https://api.supersendtx.com`
- URL: `https://api.supersendtx.com/contacts`
- Auth: HTTP bearer

Idempotent on the email address. `attributes` is merged into whatever is
already stored, so a partial sync never wipes state you set earlier.
Setting `status` to `unsubscribed` records a marketing opt-out and emits
the `contact.unsubscribed` webhook; transactional mail is unaffected.

## Request body

- UpsertContactRequest
  - `email` string, email, required
  - `external_id` string, nullable
  - `first_name` string, nullable
  - `last_name` string, nullable
  - `attributes` object, nullable: Merged into existing attributes. Send `null` to clear them.
  - `status` 'subscribed' | 'unsubscribed' | 'bounced' | 'complained': Derived on read. A contact who is suppressed, or who has opted out of newsletter mail, always reads back as `unsubscribed` — there is one source of truth for consent and this reflects it.
  - `source` 'api' | 'import' | 'dashboard' | 'agent' | 'on_site': Where the contact was first created. `on_site` means an on-site message on your website captured the address.

## Response `200`

Contact created or updated

- ContactResponse
  - `contact` Contact, required
    - `id` string, required
    - `email` string, email, required
    - `external_id` string, nullable, required: Your own id for this person, for joins back into your product
    - `first_name` string, nullable, required
    - `last_name` string, nullable, required
    - `attributes` object, required: Flat, scalar-valued product state you sync up. Segments filter on it.
    - `status` 'subscribed' | 'unsubscribed' | 'bounced' | 'complained', required: Derived on read. A contact who is suppressed, or who has opted out of newsletter mail, always reads back as `unsubscribed` — there is one source of truth for consent and this reflects it.
    - `source` 'api' | 'import' | 'dashboard' | 'agent' | 'on_site', required: Where the contact was first created. `on_site` means an on-site message on your website captured the address.
    - `last_engaged_at` string, date-time, nullable, required: Last open or click across any campaign
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required

## Other responses

- `400`: Invalid request
- `401`: Missing or invalid API key

---

[API](https://skmtc.dev/ranla/apis/supersend-tx-api.md) · [All operations](https://skmtc.dev/ranla/apis/supersend-tx-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ranla/apis/supersend-tx-api/revisions/e3e782652f50?raw)
