API reference

Messages

List and read messages, and send new messages (queued for delivery).

Every request needs x-tenant-id and an API key or OAuth token. Channel IDs are copied from Settings → Developer in the app. See Authentication.

List messages

get/api/public/v1/messages

Returns a paginated, filterable, sortable list of messages for the authenticated tenant.

Query parameters

  • pageinteger

    Default 1

  • limitinteger

    Default 25

  • sortstring

    timestampcreatedAt

    Default "timestamp"

  • orderstring

    ascdesc

    Default "desc"

  • conversationIdstring
  • contactIdstring
  • statusstring

    queuedprocessingreceivedsentdeliveredreadfailed

  • typestring

    Message type (case-insensitive), e.g. text, image, template.

  • directionstring

    inboundoutbound

  • fromstring (date-time)
  • tostring (date-time)
  • fieldsstring
Response 200Paginated list of messages
  • successboolean
  • dataobject[]
    17 child fields
    • idstring
    • conversationIdstring | null
    • contactIdstring | null
    • channelIdstring | null
    • directionstring | null

      One ofinboundoutboundnull

    • typestring | null
    • bodystring | null
    • statusstring

      One ofqueuedsentdeliveredreadfailed

    • failureReasonstring | null
    • timestampstring (date-time) | null
    • replyContextobject | null
      3 child fields
      • messageIdstring | null
      • previewstring | null
      • fromstring | null
    • mediaobject | null
      7 child fields
      • typestring | null
      • mimeTypestring | null
      • filenamestring | null
      • captionstring | null
      • sizenumber | null
      • downloadStatusstring | null

        ready (file stored, use downloadUrl), pending (inbound file still downloading), failed, or unavailable (e.g. sent by URL).

      • downloadUrlstring | null

        Public API path to download the file (same auth headers). Null until the file is stored.

    • replyobject | null

      Inbound only: the option a customer picked on an interactive button or list message.

      4 child fields
      • typestring | null

        One ofbutton_replylist_replynull

      • idstring | null

        The id you set on the button / row.

      • titlestring | null
      • descriptionstring | null
    • reactionobject | null
    • templateobject | null
      4 child fields
      • namestring | null
      • languagestring | null
      • categorystring | null
      • parametersany
    • createdAtstring (date-time)
    • updatedAtstring (date-time)
  • paginationobject
    8 child fields
    • pageinteger
    • limitinteger
    • totalinteger
    • totalPagesinteger
    • hasNextPageboolean
    • hasPrevPageboolean
    • nextCursorstring | null
    • prevCursorstring | null
  • metaobject
    1 child field
    • apiVersionstring
  • requestIdstring | null
  • timestampstring (date-time)

Errors

  • 400Malformed request or missing tenant context
  • 401Missing or invalid API key
  • 403Forbidden - developer platform disabled, key expired/disabled, or tenant mismatch
  • 422Validation failed (invalid body, unapproved template, missing variables, unsupported type)
  • 429Too many requests - rate limit exceeded
  • 500Unexpected server error
Error envelope and fixes →
curl -X GET "https://api.inaiy.com/api/public/v1/messages" \
  -H "x-tenant-id: demo" \
  -H "x-api-key: wp_live_xxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "success": true,
  "data": [
    {
      "id": "6650a1b2c3d4e5f6a7b8c9d0",
      "conversationId": "664fa1b2c3d4e5f6a7b8c9d0",
      "contactId": "663fa1b2c3d4e5f6a7b8c9d0",
      "channelId": "662fa1b2c3d4e5f6a7b8c9d0",
      "direction": "outbound",
      "type": "TEXT",
      "body": "Hello from the Public API!",
      "status": "delivered",
      "failureReason": null,
      "timestamp": "2026-07-12T09:30:00.000Z",
      "replyContext": null,
      "media": null,
      "reaction": null,
      "template": null,
      "createdAt": "2026-07-12T09:30:00.000Z",
      "updatedAt": "2026-07-12T09:31:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 87,
    "totalPages": 4,
    "hasNextPage": true,
    "hasPrevPage": false,
    "nextCursor": null,
    "prevCursor": null
  },
  "meta": {
    "apiVersion": "v1",
    "sort": {
      "field": "timestamp",
      "order": "desc"
    }
  },
  "requestId": "a1f4c2e0-9b6d-4a1e-8c3f-2d7e5b9a0c11",
  "timestamp": "2026-07-12T09:30:00.000Z"
}

Send a message (queued)

post/api/public/v1/messages

Queues a text, media, interactive, or template message for asynchronous delivery via the messaging engine. Returns 202 Accepted with the queued message id. Message sending is never synchronous.

Request bodyrequired

  • typestringrequired

    One oftextimagevideoaudiodocumenttemplatereactioninteractive

  • channelIdstringrequired

    Channel to send from. Copy it from Settings → Developer → Channels in the inaiy app.

  • contactIdstring

    Existing contact id. Required unless phone, igsid, or psid is provided.

  • phonestring

    E.164 phone (e.g. +919123577452). WhatsApp only. Used when contactId is omitted.

  • igsidstring

    Numeric Instagram scoped user id. Instagram only. The contact must already exist.

  • psidstring

    Numeric Page-scoped id of a Messenger contact. Messenger only. The contact must already exist and have messaged this Page.

  • contactNamestring

    Optional display name when createContactIfMissing creates a contact.

  • createContactIfMissingboolean

    When true and phone is provided, create the contact if it does not exist.

    Default false

  • conversationIdstring

    Optional; auto-resolved when omitted.

  • textstring

    Required for type=text (max 4096 chars).

  • mediaobject

    Required for image/video/audio/document. Provide storageKey or url.

    4 child fields
    • storageKeystring

      Media upload storageKey from POST /media/upload.

    • urlstring

      Public https URL of the file (max 2000 chars). Meta downloads it at send time. `link` is accepted as an alias.

    • filenamestring

      Document filename shown to the customer (max 255).

    • captionstring

      Caption for image, video, and document (max 1024). Ignored for audio.

  • interactiveobject

    Required for type=interactive. WhatsApp Cloud API `interactive` object; interactive.type is button, list, or cta_url. button: action.buttons (1-3) of { type: "reply", reply: { id, title<=20 } }. list: action.button (<=20) and action.sections (1-10) of { title, rows: [{ id, title<=24, description<=72 }] }. cta_url: action.name "cta_url" and action.parameters { display_text<=20, url }. body.text (<=1024) is required; header (text, or image/video/document by link) and footer.text (<=60) are optional. The customer's pick arrives as an inbound message with `reply.id`.

    5 child fields
    • typestring

      One ofbuttonlistcta_url

    • headerobject
    • bodyobject
      1 child field
      • textstring
    • footerobject
      1 child field
      • textstring
    • actionobject
  • replyToMessageIdstring

    Message id to reply to (text/media/interactive only).

  • emojistring

    Reserved for type=reaction. Reactions are not supported yet and return 422.

  • targetMessageIdstring

    Reserved for type=reaction (the message being reacted to). Reactions are not supported yet and return 422.

  • metadataobject

    Arbitrary external metadata (text/media only).

  • templateobject

    Required for type=template.

    3 child fields
    • namestring
    • languagestring
    • parametersobject

      Send-time parameters. Shape depends on the template type (standard, authentication, carousel, limited_time_offer).

      6 child fields
      • bodyany

        Positional array or named object of body variables.

      • headerobject

        Header variables: { text } for text headers, { storageKey } / { link } / { id } for media headers.

      • buttonsobject[]
        5 child fields
        • indexinteger
        • textstring

          Dynamic URL button suffix.

        • couponCodestring

          Copy-code / coupon button value.

        • payloadstring

          Dynamic quick-reply payload.

        • flowTokenstring

          Flow button token.

      • codestring

        One-time code for authentication templates.

      • cardsobject[]

        Per-card parameters for carousel templates.

        4 child fields
        • cardIndexinteger
        • headerobject
        • bodyany

          Positional array or named object of card body variables.

        • buttonsobject[]
      • limitedTimeOfferobject
        1 child field
        • expirationTimeMsinteger

          Offer expiration timestamp in ms.

Response 202Message accepted and queued
  • successboolean
  • dataobject
    4 child fields
    • idstring | null
    • statusstring
    • conversationIdstring | null
    • typestring
  • metaobject
    1 child field
    • apiVersionstring
  • requestIdstring | null
  • timestampstring (date-time)

Errors

  • 400Malformed request or missing tenant context
  • 401Missing or invalid API key
  • 403Forbidden - developer platform disabled, key expired/disabled, or tenant mismatch
  • 404Message, conversation, contact, or template not found
  • 409Conflicting state (e.g. conversation not sendable)
  • 422Validation failed (invalid body, unapproved template, missing variables, unsupported type)
  • 429Too many requests - rate limit exceeded
  • 500Unexpected server error
Error envelope and fixes →
curl -X POST "https://api.inaiy.com/api/public/v1/messages" \
  -H "x-tenant-id: demo" \
  -H "x-api-key: wp_live_xxxxxxxxxxxxxxxxxxxx"
{
  "type": "text",
  "channelId": "662fa1b2c3d4e5f6a7b8c9d0",
  "contactId": "663fa1b2c3d4e5f6a7b8c9d0",
  "text": "Hello from the Public API!"
}
Response 202
{
  "success": true,
  "data": {
    "id": "6650a1b2c3d4e5f6a7b8c9d0",
    "status": "queued",
    "conversationId": "664fa1b2c3d4e5f6a7b8c9d0",
    "type": "text"
  },
  "meta": {
    "apiVersion": "v1",
    "queued": true
  },
  "requestId": "a1f4c2e0-9b6d-4a1e-8c3f-2d7e5b9a0c11",
  "timestamp": "2026-07-12T09:30:00.000Z"
}

Get a message by id

get/api/public/v1/messages/{id}

Fetch a single message by its public id.

Path parameters

  • idstringrequired

    24-char message ObjectId

Query parameters

  • fieldsstring

    Comma-separated list of fields to return (sparse fieldset).

Response 200The message
  • successboolean
  • dataobject
    17 child fields
    • idstring
    • conversationIdstring | null
    • contactIdstring | null
    • channelIdstring | null
    • directionstring | null

      One ofinboundoutboundnull

    • typestring | null
    • bodystring | null
    • statusstring

      One ofqueuedsentdeliveredreadfailed

    • failureReasonstring | null
    • timestampstring (date-time) | null
    • replyContextobject | null
      3 child fields
      • messageIdstring | null
      • previewstring | null
      • fromstring | null
    • mediaobject | null
      7 child fields
      • typestring | null
      • mimeTypestring | null
      • filenamestring | null
      • captionstring | null
      • sizenumber | null
      • downloadStatusstring | null

        ready (file stored, use downloadUrl), pending (inbound file still downloading), failed, or unavailable (e.g. sent by URL).

      • downloadUrlstring | null

        Public API path to download the file (same auth headers). Null until the file is stored.

    • replyobject | null

      Inbound only: the option a customer picked on an interactive button or list message.

      4 child fields
      • typestring | null

        One ofbutton_replylist_replynull

      • idstring | null

        The id you set on the button / row.

      • titlestring | null
      • descriptionstring | null
    • reactionobject | null
    • templateobject | null
      4 child fields
      • namestring | null
      • languagestring | null
      • categorystring | null
      • parametersany
    • createdAtstring (date-time)
    • updatedAtstring (date-time)
  • metaobject
    1 child field
    • apiVersionstring
  • requestIdstring | null
  • timestampstring (date-time)

Errors

  • 400Malformed request or missing tenant context
  • 401Missing or invalid API key
  • 403Forbidden - developer platform disabled, key expired/disabled, or tenant mismatch
  • 404Message, conversation, contact, or template not found
  • 429Too many requests - rate limit exceeded
  • 500Unexpected server error
Error envelope and fixes →
curl -X GET "https://api.inaiy.com/api/public/v1/messages/6650a1b2c3d4e5f6a7b8c9d0" \
  -H "x-tenant-id: demo" \
  -H "x-api-key: wp_live_xxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "success": true,
  "data": {
    "id": "6650a1b2c3d4e5f6a7b8c9d0",
    "conversationId": "664fa1b2c3d4e5f6a7b8c9d0",
    "contactId": "663fa1b2c3d4e5f6a7b8c9d0",
    "channelId": "662fa1b2c3d4e5f6a7b8c9d0",
    "direction": "outbound",
    "type": "TEXT",
    "body": "Hello from the Public API!",
    "status": "delivered",
    "failureReason": null,
    "timestamp": "2026-07-12T09:30:00.000Z",
    "replyContext": null,
    "media": null,
    "reaction": null,
    "template": null,
    "createdAt": "2026-07-12T09:30:00.000Z",
    "updatedAt": "2026-07-12T09:31:00.000Z"
  },
  "meta": {
    "apiVersion": "v1"
  },
  "requestId": "a1f4c2e0-9b6d-4a1e-8c3f-2d7e5b9a0c11",
  "timestamp": "2026-07-12T09:30:00.000Z"
}

Download message media

get/api/public/v1/messages/{id}/media

Streams the file of an inbound or outbound media message (image, video, audio, document, sticker). Check `media.downloadStatus` on the message first: 409 MEDIA_NOT_READY means the inbound file is still downloading; 404 MEDIA_NOT_FOUND means the message has no stored file (e.g. media sent by URL). Pass inline=1 to get Content-Disposition: inline.

Path parameters

  • idstringrequired

    24-char message ObjectId

Query parameters

  • inlinestring

    Set to 1/true for inline Content-Disposition.

Response 200Binary file stream with Content-Type set to the media MIME type.

Errors

  • 400Malformed request or missing tenant context
  • 401Missing or invalid API key
  • 403Forbidden - developer platform disabled, key expired/disabled, or tenant mismatch
  • 404Message, conversation, contact, or template not found
  • 409Conflicting state (e.g. conversation not sendable)
  • 429Too many requests - rate limit exceeded
  • 500Unexpected server error
Error envelope and fixes →
curl -X GET "https://api.inaiy.com/api/public/v1/messages/6650a1b2c3d4e5f6a7b8c9d0/media" \
  -H "x-tenant-id: demo" \
  -H "x-api-key: wp_live_xxxxxxxxxxxxxxxxxxxx"
Response 200
string

List messages in a conversation

get/api/public/v1/conversations/{conversationId}/messages

Returns a paginated, filterable list of messages within a specific conversation.

Path parameters

  • conversationIdstringrequired

    24-char conversation ObjectId

Query parameters

  • pageinteger

    Default 1

  • limitinteger

    Default 25

  • sortstring

    timestampcreatedAt

    Default "timestamp"

  • orderstring

    ascdesc

    Default "desc"

  • conversationIdstring
  • contactIdstring
  • statusstring

    queuedprocessingreceivedsentdeliveredreadfailed

  • typestring

    Message type (case-insensitive), e.g. text, image, template.

  • directionstring

    inboundoutbound

  • fromstring (date-time)
  • tostring (date-time)
  • fieldsstring
Response 200Paginated list of messages
  • successboolean
  • dataobject[]
    17 child fields
    • idstring
    • conversationIdstring | null
    • contactIdstring | null
    • channelIdstring | null
    • directionstring | null

      One ofinboundoutboundnull

    • typestring | null
    • bodystring | null
    • statusstring

      One ofqueuedsentdeliveredreadfailed

    • failureReasonstring | null
    • timestampstring (date-time) | null
    • replyContextobject | null
      3 child fields
      • messageIdstring | null
      • previewstring | null
      • fromstring | null
    • mediaobject | null
      7 child fields
      • typestring | null
      • mimeTypestring | null
      • filenamestring | null
      • captionstring | null
      • sizenumber | null
      • downloadStatusstring | null

        ready (file stored, use downloadUrl), pending (inbound file still downloading), failed, or unavailable (e.g. sent by URL).

      • downloadUrlstring | null

        Public API path to download the file (same auth headers). Null until the file is stored.

    • replyobject | null

      Inbound only: the option a customer picked on an interactive button or list message.

      4 child fields
      • typestring | null

        One ofbutton_replylist_replynull

      • idstring | null

        The id you set on the button / row.

      • titlestring | null
      • descriptionstring | null
    • reactionobject | null
    • templateobject | null
      4 child fields
      • namestring | null
      • languagestring | null
      • categorystring | null
      • parametersany
    • createdAtstring (date-time)
    • updatedAtstring (date-time)
  • paginationobject
    8 child fields
    • pageinteger
    • limitinteger
    • totalinteger
    • totalPagesinteger
    • hasNextPageboolean
    • hasPrevPageboolean
    • nextCursorstring | null
    • prevCursorstring | null
  • metaobject
    1 child field
    • apiVersionstring
  • requestIdstring | null
  • timestampstring (date-time)

Errors

  • 400Malformed request or missing tenant context
  • 401Missing or invalid API key
  • 403Forbidden - developer platform disabled, key expired/disabled, or tenant mismatch
  • 404Message, conversation, contact, or template not found
  • 429Too many requests - rate limit exceeded
  • 500Unexpected server error
Error envelope and fixes →
curl -X GET "https://api.inaiy.com/api/public/v1/conversations/6650a1b2c3d4e5f6a7b8c9d0/messages" \
  -H "x-tenant-id: demo" \
  -H "x-api-key: wp_live_xxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "success": true,
  "data": [
    {
      "id": "6650a1b2c3d4e5f6a7b8c9d0",
      "conversationId": "664fa1b2c3d4e5f6a7b8c9d0",
      "contactId": "663fa1b2c3d4e5f6a7b8c9d0",
      "channelId": "662fa1b2c3d4e5f6a7b8c9d0",
      "direction": "outbound",
      "type": "TEXT",
      "body": "Hello from the Public API!",
      "status": "delivered",
      "failureReason": null,
      "timestamp": "2026-07-12T09:30:00.000Z",
      "replyContext": null,
      "media": null,
      "reaction": null,
      "template": null,
      "createdAt": "2026-07-12T09:30:00.000Z",
      "updatedAt": "2026-07-12T09:31:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 87,
    "totalPages": 4,
    "hasNextPage": true,
    "hasPrevPage": false,
    "nextCursor": null,
    "prevCursor": null
  },
  "meta": {
    "apiVersion": "v1",
    "sort": {
      "field": "timestamp",
      "order": "desc"
    }
  },
  "requestId": "a1f4c2e0-9b6d-4a1e-8c3f-2d7e5b9a0c11",
  "timestamp": "2026-07-12T09:30:00.000Z"
}