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

# Patch a contact

> Update only supplied contact fields. Metadata shallow-merges atomically under a row lock; null metadata values delete keys. Omitted fields remain unchanged. Requires contacts:write and an Idempotency-Key. PUT retains replacement semantics.



## OpenAPI

````yaml /api/openapi.json patch /contacts/{id}
openapi: 3.1.0
info:
  title: PowerDialer API v2
  version: 2.0.0
  description: >-
    Connect your CRM, sales workspace or reporting tools to PowerDialer using
    scoped API keys. Manage contacts and calling lists, read call evidence and
    analytics, and receive signed events. All example records and IDs are
    synthetic; replace them with values from your workspace. Shared-key v1 is
    retired. See /availability for verified release status and historical data
    coverage. Legacy outbound webhooks use a separate contract.
servers:
  - url: https://api.migration.powerdialer.ai/api/public/v2
    description: Production API v2; see /availability for verified release status.
security:
  - ApiKey: []
tags:
  - name: Authentication
  - name: Workspace members
  - name: Contacts
  - name: Calling lists
  - name: Imports
  - name: Calls
  - name: Custom dispositions
  - name: Synchronization
  - name: Analytics
  - name: Webhooks
  - name: Webhook deliveries
  - name: Incoming webhook payloads
  - name: Scheduled calls
    description: Read and manage contact-linked scheduled callbacks.
paths:
  /contacts/{id}:
    patch:
      tags:
        - Contacts
      summary: Patch a contact
      description: >-
        Update only supplied contact fields. Metadata shallow-merges atomically
        under a row lock; null metadata values delete keys. Omitted fields
        remain unchanged. Requires contacts:write and an Idempotency-Key. PUT
        retains replacement semantics.
      operationId: patchContact
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            minimum: 1
            maximum: 2147483647
          description: >-
            Numeric PowerDialer contact ID, not your CRM externalId. The contact
            must be inside the credential’s workspace and owner scope.
          example: 123
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            pattern: ^[A-Za-z0-9._:-]{1,200}$
          description: >-
            Required. Omitting this header returns 400
            `idempotency_key_required` and changes nothing; a value outside the
            pattern returns 400 `idempotency_key_invalid`. Persist one key for
            this logical operation before sending it. Reuse the same value only
            with the same method, path and body after a timeout. A changed
            request returns 409 idempotency_conflict; a matching retry returns
            the original response.
          example: 9d6b623c-c132-4d2f-b8cf-7c65d4760dbe
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactPatch'
            example:
              metadata:
                lastDunningRun: '2026-10-12'
                obsolete: null
      responses:
        '200':
          description: The updated contact, or the saved response for an identical retry.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
            RateLimit-Limit:
              schema:
                type: integer
            RateLimit-Remaining:
              schema:
                type: integer
            Idempotency-Replayed:
              schema:
                type: string
                enum:
                  - 'true'
                  - 'false'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Contact'
              example:
                ownerId: user_example
                externalId: crm-contact-123
                name: Alex Morgan
                phoneNumber: '+12125550100'
                additionalNumbers: []
                metadata:
                  source: website
                  timeZone: America/New_York
                  timeZoneSource: provided
                timeZone: America/New_York
                timeZoneSource: provided
                id: 123
                createdAt: '2026-10-08T12:00:00.000Z'
                updatedAt: '2026-10-08T12:00:00.000Z'
        default:
          description: >-
            Error. 400 invalid request; 401 invalid credential; 403 insufficient
            access; 404 not found; 409 state/idempotency conflict; 413 size
            limit; 415 body not sent as application/json; 422 verification
            failure; 429 rate limit (Retry-After seconds); 503 temporary service
            failure.
          headers:
            Retry-After:
              schema:
                type: integer
            X-Request-Id:
              schema:
                type: string
                format: uuid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: invalid_api_key
                  message: API key is invalid, expired or revoked
                  requestId: 00000000-0000-4000-8000-000000000004
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >-
            # Replace example resource IDs and ownerId with values from your
            workspace.

            : "${POWERDIALER_API_KEY:?Set POWERDIALER_API_KEY to your scoped API
            key}"

            # Set this once per operation; reuse it with the same request after
            a timeout.

            : "${POWERDIALER_REQUEST_ID:?Set POWERDIALER_REQUEST_ID to a new
            UUID for this operation}"

            curl --request PATCH \
              --url 'https://api.migration.powerdialer.ai/api/public/v2/contacts/123' \
              --header "Authorization: Bearer $POWERDIALER_API_KEY" \
              --header "Idempotency-Key: $POWERDIALER_REQUEST_ID" \
              --header 'Content-Type: application/json' \
              --data '{
              "metadata": {
                "lastDunningRun": "2026-10-12",
                "obsolete": null
              }
            }'
components:
  schemas:
    ContactPatch:
      type: object
      properties:
        externalId:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            Omitted fields stay unchanged. Stable contact ID from your CRM or
            source system, unique within this workspace. Reuse it on POST to
            update an existing contact.
        ownerId:
          type: string
          minLength: 1
          maxLength: 100
          description: >-
            Omitted fields stay unchanged. ID of an active PowerDialer workspace
            member allowed by this key. Personal keys must use their own ownerId
            from GET /me.
        name:
          type: string
          maxLength: 500
          description: Omitted fields stay unchanged. Contact display name.
        phoneNumber:
          type: string
          pattern: ^\+[1-9]\d{6,14}$
          description: >-
            Omitted fields stay unchanged. Primary number in E.164 format,
            including + and country code.
        additionalNumbers:
          type: array
          items:
            type: string
            pattern: ^\+[1-9]\d{6,14}$
          maxItems: 10
          description: Replaces the array only when supplied; omission preserves it.
        metadata:
          type: object
          additionalProperties: true
          description: >-
            Shallow merge: supplied keys replace values, absent keys stay
            unchanged, null deletes a key. The merged object is limited to
            16,000 UTF-16 code units. Top-level timezone fields take precedence;
            the resulting timezone/source pair must be valid.
        timeZone:
          anyOf:
            - type: string
              maxLength: 100
            - type: 'null'
          description: >-
            When supplied, overwrites metadata.timeZone. Omitted fields stay
            unchanged. The merged timezone/source pair must remain valid.
        timeZoneSource:
          type: string
          enum:
            - provided
            - phone_estimate
            - unknown
          description: >-
            When supplied, overwrites metadata.timeZoneSource. Omitted fields
            stay unchanged. A non-null zone requires provided or phone_estimate;
            no zone requires unknown.
      additionalProperties: false
      minProperties: 1
    Contact:
      type: object
      properties:
        id:
          type: integer
          description: PowerDialer contact ID. Use this integer in contact URLs.
        name:
          type: string
          description: Stored contact name.
        phoneNumber:
          type: string
          description: Stored primary phone number. V2 writes require E.164.
        additionalNumbers:
          type: array
          items:
            type: string
          description: Stored additional phone numbers.
        metadata:
          description: >-
            Stored JSON metadata. v2 writes use objects; legacy rows may contain
            other JSON values.
        ownerId:
          anyOf:
            - type: string
            - type: 'null'
          description: Attributed PowerDialer member ID.
        externalId:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            Your source-system identifier, or null when no identifier was
            assigned.
        createdAt:
          type: string
          format: date-time
          description: Time the contact was created, in UTC.
        updatedAt:
          type: string
          format: date-time
          description: Time the contact was last updated, in UTC.
        timeZone:
          description: >-
            Stored timezone metadata. V2 writes produce an IANA string or null;
            legacy metadata may contain another JSON value.
        timeZoneSource:
          description: >-
            Stored timezone-source metadata. V2 writes use provided,
            phone_estimate, or unknown; legacy values may differ.
      required:
        - id
        - name
        - phoneNumber
        - additionalNumbers
        - metadata
        - ownerId
        - externalId
        - createdAt
        - updatedAt
        - timeZone
        - timeZoneSource
      examples:
        - ownerId: user_example
          externalId: crm-contact-123
          name: Alex Morgan
          phoneNumber: '+12125550100'
          additionalNumbers: []
          metadata:
            source: website
            timeZone: America/New_York
            timeZoneSource: provided
          timeZone: America/New_York
          timeZoneSource: provided
          id: 123
          createdAt: '2026-10-08T12:00:00.000Z'
          updatedAt: '2026-10-08T12:00:00.000Z'
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable machine-readable error code.
            message:
              type: string
              description: Human-readable explanation.
            requestId:
              type: string
              format: uuid
              description: Request identifier to include when investigating a failure.
            details:
              type: array
              items:
                type: object
                properties:
                  path:
                    type: string
                    description: >-
                      Where the request failed, prefixed by location: `body`,
                      `body.<field>`, `query.<name>` or `path.<name>`. A
                      root-level problem reports its location alone, for example
                      `body` when no JSON object was sent, so a missing body is
                      never confused with a missing field or header.
                  message:
                    type: string
                required:
                  - path
                  - message
              description: >-
                Validation errors, when available. Each `path` names the part of
                the request that failed.
          required:
            - code
            - message
            - requestId
      required:
        - error
      examples:
        - error:
            code: insufficient_scope
            message: Requires contacts:read
            requestId: 00000000-0000-4000-8000-000000000004
        - error:
            code: invalid_request
            message: 'Request validation failed: body.url: Invalid url'
            requestId: 00000000-0000-4000-8000-000000000004
            details:
              - path: body.url
                message: Invalid url
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      bearerFormat: pd_<live|test>_<credential UUID>.<random secret>
      description: >-
        Issued in Developers. Workspace/owner/scopes come from credential, never
        acting-user headers. API keys cannot manage API credentials.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.