> ## 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.

# Get a message

> Returns one message with every delivery attempt and engagement event recorded against it, both oldest first and each capped at 500 rows. Engagement is an addition to the record rather than the record itself, so an unavailable engagement store yields an empty `engagementEvents` rather than a failure. A query that fails mid-flight yields no rows rather than an error, so a transient outage of the log store reads as a 404. Requires the `messages:read` scope.



## OpenAPI

````yaml /api-reference/openapi.json get /api/v1/user/messages/{jobId}
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/messages/{jobId}:
    get:
      tags:
        - Messages
      summary: Get a message
      description: >-
        Returns one message with every delivery attempt and engagement event
        recorded against it, both oldest first and each capped at 500 rows.
        Engagement is an addition to the record rather than the record itself,
        so an unavailable engagement store yields an empty `engagementEvents`
        rather than a failure. A query that fails mid-flight yields no rows
        rather than an error, so a transient outage of the log store reads as a
        404. Requires the `messages:read` 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
        - in: path
          name: jobId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageDetailResponse'
        '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'
        '404':
          description: The organization has no message under that job id
          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'
        '503':
          description: The message log store is unreachable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKey: []
        - apiKeyBearer: []
components:
  schemas:
    MessageDetailResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
        data:
          $ref: '#/components/schemas/MessageDetail'
      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
    MessageDetail:
      type: object
      properties:
        jobId:
          type: string
        messageId:
          type: string
          description: >-
            Taken from the most recent attempt, which is the address the message
            went out as
        senderAddress:
          type: string
          format: email
        campaignId:
          type: string
          format: uuid
          nullable: true
        contactId:
          type: string
          format: uuid
          nullable: true
          description: >-
            The contact the message was addressed to, when the send was
            contact-driven
        recipients:
          type: array
          items:
            type: string
          description: Every distinct recipient the attempts cover
        deliveryAttempts:
          type: array
          items:
            $ref: '#/components/schemas/MessageDeliveryAttempt'
          description: Oldest attempt first, capped at the 500 most recent rows
        engagementEvents:
          type: array
          items:
            $ref: '#/components/schemas/MessageEngagementEntry'
          description: >-
            Opens, clicks and complaints, oldest first and capped at 500 rows.
            Empty when the engagement store holds nothing for the message, and
            also when it is unavailable
        retentionDays:
          type: number
          example: 90
          description: How many days of message history are retained before rows age out
      required:
        - jobId
        - messageId
        - senderAddress
        - campaignId
        - contactId
        - recipients
        - deliveryAttempts
        - engagementEvents
        - retentionDays
    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
    MessageDeliveryAttempt:
      type: object
      properties:
        recipient:
          type: string
          format: email
        status:
          type: string
          enum:
            - delivered
            - bounced
            - deferred
        smtpCode:
          type: number
          nullable: true
          example: 250
        smtpMessage:
          type: string
          nullable: true
        mxHost:
          type: string
          nullable: true
          example: aspmx.l.google.com
          description: The receiving mail exchanger this attempt was made against
        outboundIp:
          type: string
          nullable: true
          description: The IP the attempt was sent from
        retryCount:
          type: number
          description: Zero on the first attempt
        attemptedAt:
          type: string
          format: date-time
      required:
        - recipient
        - status
        - smtpCode
        - smtpMessage
        - mxHost
        - outboundIp
        - retryCount
        - attemptedAt
    MessageEngagementEntry:
      type: object
      properties:
        type:
          type: string
          enum:
            - opened
            - clicked
            - complained
        recipient:
          type: string
          format: email
        userAgent:
          type: string
          nullable: true
        remoteIp:
          type: string
          nullable: true
        occurredAt:
          type: string
          format: date-time
      required:
        - type
        - recipient
        - userAgent
        - remoteIp
        - occurredAt
  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.

````