---
title: "POST /v1/workspaces/{workspaceId}/contacts/upsert"
method: POST
path: "/v1/workspaces/{workspaceId}/contacts/upsert"
---

# POST /v1/workspaces/{workspaceId}/contacts/upsert

`POST /v1/workspaces/{workspaceId}/contacts/upsert`

## Request

- Base URL: `https://api.bangermail.com`
- URL: `https://api.bangermail.com/v1/workspaces/{workspaceId}/contacts/upsert`
- Auth: HTTP bearer

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `email` string, email, required
  - `display_name` string
  - `attributes` object
  - `status` 'subscribed' | 'unsubscribed' | 'bounced' | 'complained', required
  - `consent_evidence` object
    - `source` string
    - `reference` string
    - `observed_at` string, date-time
    - `statement` string
  - `consent_confirmed` boolean

## Response `200`

Canonical read-back or idempotent receipt. Provider acceptance is sent; delivered requires a delivery event and does not prove inbox placement.

- object
  - `data` object, required
    - `id` string, uuid, required
    - `email` string, email, required
    - `display_name` string, nullable, required
    - `attributes` object, required
    - `status` 'subscribed' | 'unsubscribed' | 'bounced' | 'complained', required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `suppressed` boolean, required
    - `suppression_reason` string, nullable, required
    - `sources` object[], required
      - `kind` string, required
      - `reference` string, required
      - `connection_id` string, uuid, nullable, required
      - `metadata` object, required
      - `first_seen_at` string, date-time, required
      - `last_seen_at` string, date-time, required
    - `lists` object[], required
      - `id` string, uuid, required
      - `name` string, required
    - `subscription_status` string, required
    - `consent_evidence` object[], required
      - `kind` string, required
      - `reference` string, required
      - `connection_id` string, uuid, nullable, required
      - `metadata` object, required
      - `first_seen_at` string, date-time, required
      - `last_seen_at` string, date-time, required
    - `replayed` boolean, required

## Other responses

- `400`: Invalid input or missing operating product.
- `403`: Existing OAuth scope or product boundary denied.
- `409`: Stale version or idempotency conflict.
- `422`: Consent, suppression, personalization, or readiness blocker.

---

[API](https://skmtc.dev/bangermail/apis/banger-api.md) · [All operations](https://skmtc.dev/bangermail/apis/banger-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bangermail/apis/banger-api/revisions/a149909267f9?raw)
