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

# Set the primary contact

> Idempotently ensure an address is the recipient's **primary** contact for a medium — create it if absent, update the existing primary in place if the address differs (which resets `verified_at`), or no-op if it already matches. Returns the resulting primary contact (`200`) either way, so a "keep the primary email current" sync is a single call.

💡 Sync this **server-side** so the address never rides a browser request.

Idempotently ensure an address is the recipient's **primary** contact for a medium. Unlike [add contact](/api-reference/endpoint/recipients/contacts/create-contact) (which is strict and `409`s on conflict), this is a create-or-update: it creates the primary if absent, updates the existing primary in place if the address differs (which resets `verified_at`), or no-ops if it already matches — always `200`.

💡 This is the one call a **server-side** sync needs to keep a recipient's primary email current — no list-then-diff. Sync it server-side so the address never rides a browser request.


## OpenAPI

````yaml PUT /recipients/{recipient_id}/contacts
openapi: 3.0.3
info:
  title: Bodhveda Notifications API
  version: '1.0'
  description: API for sending notifications to recipients or broadcasting to all.
servers: []
security: []
paths:
  /recipients/{recipient_id}/contacts:
    put:
      tags:
        - Contacts
      summary: Set the primary contact
      description: >-
        Idempotently ensure an address is the recipient's **primary** contact
        for a medium — create it if absent, update the existing primary in place
        if the address differs (which resets `verified_at`), or no-op if it
        already matches. Returns the resulting primary contact (`200`) either
        way, so a "keep the primary email current" sync is a single call.


        💡 Sync this **server-side** so the address never rides a browser
        request.
      operationId: setPrimaryRecipientContact
      parameters:
        - name: recipient_id
          in: path
          required: true
          schema:
            type: string
          description: The unique identifier of the recipient.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetPrimaryContactPayload'
      responses:
        '200':
          description: The resulting primary contact.
          content:
            application/json:
              examples:
                Primary set:
                  summary: Primary Contact Response
                  value:
                    message: Primary contact set
                    data:
                      id: 1
                      medium: email
                      address: alice@example.com
                      is_primary: true
                      verified_at: null
                      created_at: '2025-11-07T05:31:56Z'
                      updated_at: '2025-11-07T05:31:56Z'
        '409':
          description: >-
            The target address is already a different contact for this recipient
            and medium.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - BearerAuthWithAPIKeyWithEitherScope: []
      x-codeSamples:
        - lang: curl
          source: >-
            curl -X PUT
            https://api.bodhveda.com/recipients/recipient_123/contacts \
              -H "Authorization: Bearer bv_xxxxxxxxx" \
              -H "Content-Type: application/json" \
              -d '{
                "medium": "email",
                "address": "alice@example.com"
              }'
components:
  schemas:
    SetPrimaryContactPayload:
      type: object
      properties:
        medium:
          type: string
          description: The delivery transport. Only `email` is exercised today.
          enum:
            - email
            - sms
            - web_push
            - mobile_push
        address:
          type: string
          description: >-
            The address to make primary. For email it must contain `@` and is
            stored lowercased.
      required:
        - medium
        - address
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
        details:
          type: string
  securitySchemes:
    BearerAuthWithAPIKeyWithEitherScope:
      type: http
      scheme: bearer
      bearerFormat: APIKey
      description: >-
        Bearer authentication header of the form `Bearer bv_xxxxxxxxx`, where
        `bv_xxxxxxxxx` is your **API Key** with `Full access` or `Recipient
        acess` scope.

````