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

# Create or Update Contact

> Create or update a contact. This is an **upsert keyed on email** (within the workspace): if a contact with the same email exists it is updated, otherwise it is created. On an existing contact, scalar fields are only filled where they are currently empty (customer-entered values are preserved), and tags are attached only when the contact is newly created. The response `status` field tells you which happened. Contacts created through the API key are stamped `primary_source: "public_api"`.

Create a contact, or update an existing one with the same email. The response `status` field (`created`, `updated`, or `unchanged`) tells you which happened, so integrations can branch without a separate lookup.

On an existing contact, scalar fields are only filled where they are currently empty — customer-entered values are never overwritten — and tags are attached only when the contact is newly created.


## OpenAPI

````yaml POST /contacts
openapi: 3.1.0
info:
  title: Feedspace API
  description: Feedspace API v3 - Feedback and testimonial management platform
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.feedspace.io/v3
security: []
paths:
  /contacts:
    post:
      tags:
        - Contacts
      description: >-
        Create or update a contact. This is an **upsert keyed on email** (within
        the workspace): if a contact with the same email exists it is updated,
        otherwise it is created. On an existing contact, scalar fields are only
        filled where they are currently empty (customer-entered values are
        preserved), and tags are attached only when the contact is newly
        created. The response `status` field tells you which happened. Contacts
        created through the API key are stamped `primary_source: "public_api"`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  maxLength: 255
                  description: Contact email. The upsert key; lowercased and trimmed.
                name:
                  type: string
                  maxLength: 255
                phone:
                  type: string
                  maxLength: 50
                country:
                  type: string
                  maxLength: 100
                state:
                  type: string
                  maxLength: 100
                city:
                  type: string
                  maxLength: 100
                zipcode:
                  type: string
                  maxLength: 20
                company:
                  type: string
                  maxLength: 255
                date_added:
                  type: string
                  format: date
                  description: >-
                    Date the contact was added (YYYY-MM-DD). Common date formats
                    are accepted and normalised.
                external_metadata:
                  type: object
                  description: >-
                    Arbitrary key/value metadata from your system. Merged per
                    key on update (existing keys are preserved).
                tag_ids:
                  type: array
                  items:
                    type: integer
                  description: >-
                    Tag IDs to attach (must exist in this workspace). Applied
                    only when the contact is newly created.
                tags:
                  type: array
                  items:
                    type: string
                    maxLength: 100
                  description: >-
                    Tag names to attach; missing tags are auto-created. Applied
                    only when the contact is newly created.
                primary_source:
                  type: string
                  enum:
                    - csv
                    - public_api
                    - review_submission
                    - manual
                    - social_import
                    - stripe
                  description: >-
                    Override the source stamp. Defaults to `public_api` for
                    API-key requests. Locked to the first value; never changed
                    on later upserts.
              required:
                - email
      responses:
        '200':
          description: >-
            Contact upserted. Returns `200` when the contact was updated or
            unchanged, `201` when a new contact was created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - created
                      - updated
                      - unchanged
                    description: >-
                      Which operation occurred. Use this to branch in
                      integrations.
                  contact:
                    $ref: '#/components/schemas/Contact'
              examples:
                success:
                  value:
                    status: created
                    contact:
                      id: 8801
                      email: jordan@example.com
                      name: Jordan Lee
                      phone: null
                      primary_source: public_api
                      country: null
                      state: null
                      city: null
                      zipcode: null
                      company: Acme
                      date_added: '2026-05-01'
                      date_added_label: May 1, 2026
                      is_unsubscribed: false
                      unsubscribe_reason: null
                      unsubscribed_at: null
                      enriched_at: null
                      tag_ids:
                        - 3
                        - 7
                      has_reviewed: false
                      created_at: '2026-05-01T10:00:00.000000Z'
                      updated_at: '2026-05-01T10:00:00.000000Z'
      security:
        - basicAuth: []
components:
  schemas:
    Contact:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
        name:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
        primary_source:
          type: string
          description: >-
            How the contact first entered the workspace: csv, public_api,
            review_submission, manual, social_import, or stripe. Locked to the
            first source.
        country:
          type:
            - string
            - 'null'
        state:
          type:
            - string
            - 'null'
        city:
          type:
            - string
            - 'null'
        zipcode:
          type:
            - string
            - 'null'
        company:
          type:
            - string
            - 'null'
        date_added:
          type:
            - string
            - 'null'
          description: YYYY-MM-DD.
        date_added_label:
          type:
            - string
            - 'null'
          description: Human-readable date, e.g. "May 1, 2026".
        is_unsubscribed:
          type: boolean
        unsubscribe_reason:
          type:
            - string
            - 'null'
        unsubscribed_at:
          type:
            - string
            - 'null'
        enriched_at:
          type:
            - string
            - 'null'
        tag_ids:
          type: array
          items:
            type: integer
        has_reviewed:
          type: boolean
          description: True if this contact has submitted or been imported as a review.
        created_at:
          type: string
        updated_at:
          type: string
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        HTTP Basic Authentication using API Key and Secret Key. The credentials
        should be Base64 encoded in the format 'api_key:secret_key'. You can
        obtain your API Key and Secret Key from Feedspace → Automation → API
        (https://app.feedspace.io/automation/api).

````