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

# Create contacts in bulk

> Creates the contacts in chunks and reports the outcome per row: a chunk that fails is retried row by row so the sound rows still persist. The status is always 201, even when every row failed, so read `createdCount`, `failedCount` and the `errors` array rather than the status to learn what happened. Requires the `contacts:write` scope.



## OpenAPI

````yaml /api-reference/openapi.json post /api/v1/user/contacts/bulk
openapi: 3.0.0
info:
  title: Brudcast API
  version: 1.0.0
servers:
  - url: https://core-service.prod.brudcast.com
    description: Production
security: []
tags:
  - name: Analytics
    x-displayName: Analytics
  - name: Campaigns
    x-displayName: Campaigns
  - name: Contacts
    x-displayName: Contacts
  - name: Mailboxes
    x-displayName: Mailboxes
  - name: Messages
    x-displayName: Messages
  - name: Sender Identities
    x-displayName: Sender Identities
  - name: Sending Domains
    x-displayName: Sending Domains
  - name: Templates
    x-displayName: Templates
  - name: Webhooks
    x-displayName: Webhooks
paths:
  /api/v1/user/contacts/bulk:
    post:
      tags:
        - Contacts
      summary: Create contacts in bulk
      description: >-
        Creates the contacts in chunks and reports the outcome per row: a chunk
        that fails is retried row by row so the sound rows still persist. The
        status is always 201, even when every row failed, so read
        `createdCount`, `failedCount` and the `errors` array rather than the
        status to learn what happened. Requires the `contacts:write` scope.
      parameters:
        - in: header
          name: X-Organization-Id
          required: false
          description: >-
            Required when authenticating with an access token. Optional with an
            API key, whose own organization binding is authoritative; a value
            contradicting it is refused with 403.
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                contacts:
                  type: array
                  items:
                    type: object
                    properties:
                      firstName:
                        type: string
                        minLength: 1
                        maxLength: 255
                      lastName:
                        type: string
                        minLength: 1
                        maxLength: 255
                      displayName:
                        type: string
                        minLength: 1
                        maxLength: 255
                      timezone:
                        type: string
                        maxLength: 50
                      language:
                        type: string
                        maxLength: 10
                      status:
                        enum:
                          - active
                          - inactive
                          - archived
                      tags:
                        type: array
                        items:
                          type: string
                      customFields:
                        type: object
                        additionalProperties:
                          anyOf:
                            - type: string
                            - type: number
                            - type: boolean
                            - type: array
                            - type: object
                      notes:
                        type: string
                        maxLength: 5000
                      emails:
                        type: array
                        items:
                          type: object
                          properties:
                            email:
                              type: string
                              format: email
                            isPrimary:
                              type: boolean
                          required:
                            - email
                          additionalProperties: false
                      smsNumbers:
                        type: array
                        items:
                          type: object
                          properties:
                            phoneNumber:
                              type: string
                              minLength: 10
                              maxLength: 20
                            countryCode:
                              type: string
                              minLength: 1
                              maxLength: 3
                            isPrimary:
                              type: boolean
                          required:
                            - phoneNumber
                            - countryCode
                          additionalProperties: false
                      whatsappAccounts:
                        type: array
                        items:
                          type: object
                          properties:
                            phoneNumber:
                              type: string
                              minLength: 1
                            countryCode:
                              type: string
                              minLength: 1
                            status:
                              enum:
                                - verified
                                - unverified
                                - blocked
                            isPrimary:
                              type: boolean
                            isBusinessAccount:
                              type: boolean
                          required:
                            - phoneNumber
                            - countryCode
                          additionalProperties: false
                      telegramAccounts:
                        type: array
                        items:
                          type: object
                          properties:
                            phoneNumber:
                              type: string
                              minLength: 1
                            countryCode:
                              type: string
                              minLength: 1
                            username:
                              type: string
                              minLength: 1
                            isPrimary:
                              type: boolean
                          required:
                            - phoneNumber
                            - countryCode
                          additionalProperties: false
                      imessageAccounts:
                        type: array
                        items:
                          type: object
                          properties:
                            appleId:
                              type: string
                              format: email
                            phoneNumber:
                              type: string
                            isPrimary:
                              type: boolean
                          required:
                            - appleId
                          additionalProperties: false
                      pushNotifications:
                        type: array
                        items:
                          type: object
                          properties:
                            deviceToken:
                              type: string
                            platform:
                              enum:
                                - ios
                                - android
                                - web
                            appVersion:
                              type: string
                            deviceInfo:
                              type: object
                              additionalProperties:
                                anyOf:
                                  - type: string
                                  - type: number
                                  - type: boolean
                                  - type: array
                                  - type: object
                            isPrimary:
                              type: boolean
                          required:
                            - deviceToken
                            - platform
                          additionalProperties: false
                    additionalProperties: false
                  minItems: 1
                  maxItems: 500
              required:
                - contacts
              additionalProperties: false
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactBulkCreateResultResponse'
        '401':
          description: The credential is missing, malformed, revoked or expired
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            The key lacks the scope the endpoint requires, or the organization
            does not match the credential
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: The payload or query string failed validation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
        '429':
          description: >-
            Rate limit exceeded; retry after the number of seconds in
            `retryAfter`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitErrorResponse'
      security:
        - apiKey: []
        - apiKeyBearer: []
components:
  schemas:
    ContactBulkCreateResultResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
        data:
          $ref: '#/components/schemas/ContactBulkCreateResult'
      required:
        - success
        - message
        - data
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: Resource not found
        code:
          type: string
          enum:
            - E_VALIDATION_ERROR
            - E_UNAUTHORIZED_ACCESS
            - E_UNAUTHORIZED
            - E_FORBIDDEN
            - E_INSUFFICIENT_SCOPE
            - E_ROW_NOT_FOUND
            - E_TOO_MANY_REQUESTS
            - E_BUSINESS_RULE_VIOLATION
            - E_CAMPAIGN_NOT_SENDABLE
            - INSUFFICIENT_CREDITS
            - SUBSCRIPTION_REQUIRED
          example: E_ROW_NOT_FOUND
      required:
        - success
        - message
        - code
    ValidationErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: The payload is invalid
        code:
          type: string
          enum:
            - E_VALIDATION_ERROR
            - E_UNAUTHORIZED_ACCESS
            - E_UNAUTHORIZED
            - E_FORBIDDEN
            - E_INSUFFICIENT_SCOPE
            - E_ROW_NOT_FOUND
            - E_TOO_MANY_REQUESTS
            - E_BUSINESS_RULE_VIOLATION
            - E_CAMPAIGN_NOT_SENDABLE
            - INSUFFICIENT_CREDITS
            - SUBSCRIPTION_REQUIRED
          example: E_VALIDATION_ERROR
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ValidationErrorItem'
      required:
        - success
        - message
        - code
        - errors
    RateLimitErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: Too many requests
        code:
          type: string
          enum:
            - E_VALIDATION_ERROR
            - E_UNAUTHORIZED_ACCESS
            - E_UNAUTHORIZED
            - E_FORBIDDEN
            - E_INSUFFICIENT_SCOPE
            - E_ROW_NOT_FOUND
            - E_TOO_MANY_REQUESTS
            - E_BUSINESS_RULE_VIOLATION
            - E_CAMPAIGN_NOT_SENDABLE
            - INSUFFICIENT_CREDITS
            - SUBSCRIPTION_REQUIRED
          example: E_TOO_MANY_REQUESTS
        retryAfter:
          type: number
          example: 60
      required:
        - success
        - message
        - code
        - retryAfter
    ContactBulkCreateResult:
      type: object
      properties:
        created:
          type: array
          items:
            $ref: '#/components/schemas/Contact'
        createdCount:
          type: number
        failedCount:
          type: number
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ContactBulkCreateError'
      required:
        - created
        - createdCount
        - failedCount
        - errors
    ValidationErrorItem:
      type: object
      properties:
        field:
          type: string
          example: emailAddress
        rule:
          type: string
          example: email
        message:
          type: string
          example: The emailAddress field must be a valid email address
      required:
        - field
        - rule
        - message
    Contact:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organizationId:
          type: string
          format: uuid
        firstName:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        displayName:
          type: string
          nullable: true
          description: >-
            Derived on create from the first and last name, then the first email
            address, falling back to "Unnamed Contact"
        timezone:
          type: string
          nullable: true
          example: Africa/Lagos
        language:
          type: string
          nullable: true
          example: en
        status:
          type: string
          enum:
            - active
            - inactive
            - archived
          nullable: true
        customFields:
          type: object
          additionalProperties: true
          nullable: true
          description: Values keyed by the organization's custom field keys
        notes:
          type: string
          nullable: true
        lastActivityAt:
          type: string
          format: date-time
          nullable: true
        tags:
          type: array
          items:
            type: string
          description: >-
            Tag names, kept for compatibility with the tag records. Empty when
            the query did not load the tags
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        emails:
          type: array
          items:
            $ref: '#/components/schemas/ContactEmail'
          description: Preloaded wherever a contact is returned
        smsNumbers:
          type: array
          items:
            $ref: '#/components/schemas/ContactSms'
          description: >-
            Preloaded by the contact endpoints. Absent where a contact is
            embedded in a segment or list member listing, which loads email
            addresses only
        whatsappAccounts:
          type: array
          items:
            $ref: '#/components/schemas/ContactWhatsapp'
          description: >-
            Preloaded by the contact endpoints. Absent where a contact is
            embedded in a segment or list member listing, which loads email
            addresses only
        telegramAccounts:
          type: array
          items:
            $ref: '#/components/schemas/ContactTelegram'
          description: >-
            Preloaded by the contact endpoints. Absent where a contact is
            embedded in a segment or list member listing, which loads email
            addresses only
        imessageAccounts:
          type: array
          items:
            $ref: '#/components/schemas/ContactImessage'
          description: >-
            Preloaded by the contact endpoints. Absent where a contact is
            embedded in a segment or list member listing, which loads email
            addresses only
        pushNotifications:
          type: array
          items:
            $ref: '#/components/schemas/ContactPushNotification'
          description: >-
            Preloaded by the contact endpoints. Absent where a contact is
            embedded in a segment or list member listing, which loads email
            addresses only
        tagRecords:
          type: array
          items:
            $ref: '#/components/schemas/ContactTag'
          description: >-
            The tag records behind `tags`. Absent where a contact is embedded in
            a list member listing
        listMemberships:
          type: array
          items:
            $ref: '#/components/schemas/ContactListMembership'
          description: Present only when a single contact is fetched by id
      required:
        - id
        - organizationId
        - firstName
        - lastName
        - displayName
        - timezone
        - language
        - status
        - customFields
        - notes
        - lastActivityAt
        - tags
        - createdAt
        - updatedAt
    ContactBulkCreateError:
      type: object
      properties:
        index:
          type: number
          description: >-
            Zero-based position of the failed entry in the submitted `contacts`
            array
        message:
          type: string
      required:
        - index
        - message
    ContactEmail:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        organizationId:
          type: string
          format: uuid
        email:
          type: string
          format: email
          description: Stored encrypted at rest and returned in the clear
        status:
          type: string
          enum:
            - verified
            - unverified
            - bounced
            - complained
            - suppressed
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        bounceCount:
          type: number
        complaintCount:
          type: number
        verifiedAt:
          type: string
          format: date-time
          nullable: true
        lastBouncedAt:
          type: string
          format: date-time
          nullable: true
        lastComplainedAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - organizationId
        - email
        - status
        - isPrimary
        - bounceCount
        - complaintCount
        - verifiedAt
        - lastBouncedAt
        - lastComplainedAt
        - createdAt
        - updatedAt
    ContactSms:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        phoneNumber:
          type: string
          example: '+2348012345678'
          description: Stored encrypted at rest and returned in the clear
        countryCode:
          type: string
          example: NG
        status:
          type: string
          enum:
            - verified
            - unverified
            - invalid
            - opted_out
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        verifiedAt:
          type: string
          format: date-time
          nullable: true
        optedOutAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - phoneNumber
        - countryCode
        - status
        - isPrimary
        - verifiedAt
        - optedOutAt
        - createdAt
        - updatedAt
    ContactWhatsapp:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        phoneNumber:
          type: string
          example: '+2348012345678'
          description: Stored encrypted at rest and returned in the clear
        countryCode:
          type: string
          example: NG
        status:
          type: string
          enum:
            - verified
            - unverified
            - blocked
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        isBusinessAccount:
          type: boolean
        lastSeenAt:
          type: string
          format: date-time
          nullable: true
        verifiedAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - phoneNumber
        - countryCode
        - status
        - isPrimary
        - isBusinessAccount
        - lastSeenAt
        - verifiedAt
        - createdAt
        - updatedAt
    ContactTelegram:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        phoneNumber:
          type: string
          example: '+2348012345678'
          description: Stored encrypted at rest and returned in the clear
        countryCode:
          type: string
          example: NG
        username:
          type: string
          nullable: true
          description: >-
            The Telegram handle, stored encrypted at rest and returned in the
            clear
        status:
          type: string
          enum:
            - active
            - inactive
            - blocked
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        lastActiveAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - phoneNumber
        - countryCode
        - username
        - status
        - isPrimary
        - lastActiveAt
        - createdAt
        - updatedAt
    ContactImessage:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        appleId:
          type: string
          format: email
          description: Stored encrypted at rest and returned in the clear
        phoneNumber:
          type: string
          nullable: true
          example: '+2348012345678'
          description: Stored encrypted at rest and returned in the clear
        status:
          type: string
          enum:
            - verified
            - unverified
            - invalid
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        verifiedAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - appleId
        - phoneNumber
        - status
        - isPrimary
        - verifiedAt
        - createdAt
        - updatedAt
    ContactPushNotification:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        deviceToken:
          type: string
          description: The APNs, FCM or web push registration token
        platform:
          type: string
          enum:
            - ios
            - android
            - web
        status:
          type: string
          enum:
            - active
            - inactive
            - expired
        appVersion:
          type: string
          nullable: true
          example: 3.4.1
        deviceInfo:
          type: object
          additionalProperties: true
          nullable: true
          description: Free-form device metadata supplied when the device was registered
        isPrimary:
          type: boolean
          description: >-
            Setting this does not demote the contact's other records on the same
            channel, so more than one can be primary at once
        lastUsedAt:
          type: string
          format: date-time
          nullable: true
        expiresAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - contactId
        - deviceToken
        - platform
        - status
        - appVersion
        - deviceInfo
        - isPrimary
        - lastUsedAt
        - expiresAt
        - createdAt
        - updatedAt
    ContactTag:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organizationId:
          type: string
          format: uuid
          description: >-
            Absent from the unpaginated listing, which selects the id and name
            only
        name:
          type: string
          example: newsletter
        contactCount:
          type: number
          description: >-
            Contacts carrying the tag. Reported as 0 wherever the tag is
            returned without the aggregate, which includes the unpaginated
            listing and every tag embedded in a contact or contact list
          example: 42
        createdAt:
          type: string
          format: date-time
          description: >-
            Absent from the unpaginated listing, which selects the id and name
            only
        updatedAt:
          type: string
          format: date-time
          description: >-
            Absent from the unpaginated listing, which selects the id and name
            only
      required:
        - id
        - name
        - contactCount
    ContactListMembership:
      type: object
      properties:
        id:
          type: string
          format: uuid
        contactId:
          type: string
          format: uuid
        contactListId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - subscribed
            - unsubscribed
        subscribedAt:
          type: string
          format: date-time
          nullable: true
        unsubscribedAt:
          type: string
          format: date-time
          nullable: true
        unsubscribeReason:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        contact:
          $ref: '#/components/schemas/Contact'
          description: >-
            Present when the memberships of one list are paged, carrying the
            member with their email addresses
        contactList:
          $ref: '#/components/schemas/ContactList'
          description: Present when the memberships are embedded in a single contact
      required:
        - id
        - contactId
        - contactListId
        - status
        - subscribedAt
        - unsubscribedAt
        - unsubscribeReason
        - createdAt
        - updatedAt
    ContactList:
      type: object
      properties:
        id:
          type: string
          format: uuid
        cuid:
          type: string
          description: Stable public identifier for the list
        organizationId:
          type: string
          format: uuid
        name:
          type: string
          example: Product announcements
        description:
          type: string
          nullable: true
        status:
          type: string
          enum:
            - active
            - inactive
            - archived
        preferredChannels:
          type: array
          items:
            type: string
            enum:
              - email
              - sms
              - imessage
              - telegram
              - push
              - whatsapp
          description: Channels a campaign should prefer when sending to this list
        tags:
          type: array
          items:
            type: string
          description: >-
            Tag names, kept for compatibility with the tag records. Empty when
            the query did not load the tags
        isDefault:
          type: boolean
          description: Whether this is the organization's default list
        subscriberCount:
          type: number
          description: >-
            Subscribed memberships, maintained incrementally as contacts join
            and leave
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        tagRecords:
          type: array
          items:
            $ref: '#/components/schemas/ContactTag'
          description: >-
            The tag records behind `tags`, present whenever the list is read
            directly
      required:
        - id
        - cuid
        - organizationId
        - name
        - description
        - status
        - preferredChannels
        - tags
        - isDefault
        - subscriberCount
        - createdAt
        - updatedAt
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        An organization API key, prefixed `bk_live_`. Takes precedence over
        `Authorization` when both are sent. The key is bound to one
        organization, and the scopes it was issued with are enforced per
        endpoint.
    apiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: bk_live_...
      description: >-
        The same organization API key sent as `Authorization: Bearer
        bk_live_...`. Accepted only when the value begins with `bk_` and no
        `X-API-Key` header is present.

````