Skip to main content

Get inbox messages

Retrieve a paginated list of email messages available in the Woodpecker inbox. You can use the available parameters to narrow down the results by mailbox, campaign, prospect status, or interest level. In standard Woodpecker accounts and agency HQs, the /inbox endpoint lets you access emails from mailboxes connected by the owner of the API key. In agency client accounts, it provides access to all connected mailboxes.

If you'd like to retrieve responses for a specific prospect, use the v2/prospects endpoint

Request

Endpoint

GET https://api.woodpecker.co/rest/v2/inbox/messages

Headers

x-api-key: {YOUR_API_KEY}

For details on how to authenticate your requests, please see the authentication guide.

Parameters

You can use the query parameters below to filter inbox messages. Each filter is optional - if you omit a parameter, that filter will not be applied. If no parameters are provided, the request will return unfiltered inbox messages based on the default pagination settings.

ParameterRequiredTypeDescription
prospect_statusNostringFilters inbox messages by the prospect's current status. Available values: RESPONDED, AUTOREPLIED, BOUNCED, BLACKLISTED, OPT_OUT. Mutually exclusive with prospect_interest_level and out_of_campaign
prospect_interest_levelNostringFilters inbox messages by the prospect's interest level. Available values: INTERESTED, MAYBE_LATER, NOT_INTERESTED, NOT_MARKED. Mutually exclusive with prospect_status and out_of_campaign
mailbox_idsNostring (comma-separated integers)Retrieve only responses fetched from the specified mailbox IMAP accounts. Use /mailboxes endpoint to fetch mailbox details
campaign_idsNostring (comma-separated integers)Retrieve only responses associated with given campaigns. Use /campaign endpoints to fetch campaign details
search_phrasesNoarray[string]Filters messages using up to 20 search phrases. Phrases must be at least 3 characters long. Phrases can be provided as a comma-separated list search_phrases=one,two,three with a combined total length of 100 characters, or as repeated parameters search_phrases=one&search_phrases=two, where each phrase can be up to 100 characters long
readNobooleanWhether to list messages that are marked as read or unread. If not specified, both will be included.
out_of_campaignNostringFilters inbox messages that are not associated with any prospects. Accepted value: YES. Mutually exclusive with prospect_status and prospect_interest_level
per_pageNointegerNumber of records per page. Default: 10, maximum: 50
next_page_cursorNostringCursor used to retrieve a specific page of results. Use null to start from the first page. Only values returned in the next_page_cursor field of a previous response are accepted. Mutually exclusive with previous_page_cursor, but both can be null. See the pagination section for more details
previous_page_cursorNostringCursor used to retrieve the previous page of results. Use null to start from the first page. Mutually exclusive with next_page_cursor, but both can be null. Only values returned in the previous_page_cursor field of a previous response are accepted.

Request samples

Retrieve 10 latest responses marked as INTERESTED

curl --request GET \
--url "https://api.woodpecker.co/rest/v2/inbox/messages?per_page=5&prospect_interest_level=INTERESTED" \
--header "x-api-key: {YOUR_API_KEY}"

Response

Response examples

A list of responses retrieved from the Woodpecker inbox. The responses are sorted by the most recently received message

{
"content": [
{
"id": 123456,
"prospect_id": 987654,
"read": true,
"bounced": false,
"global_prospect_status": "ACTIVE",
"stamp": "2026-03-05T17:57:00Z",
"subject": "Re: Subject line of the response",
"body": {
"html": "<div>This is a reply in HTML format.</div>"
},
"campaigns": [
{
"id": 1763200,
"name": "Associated campaign name",
"status": "RUNNING",
"prospect": {
"campaign_prospect_id": 654321,
"interest_level": {
"level": "NOT_MARKED",
"ai_detected": false
},
"status": "PAUSED",
"resume_followup_after": "2026-03-12T00:00:00Z",
"status_reasons": [
{
"reason": "AUTOREPLIED"
}
],
"substatus": {
"created_at": "2026-01-15T14:00:00.000Z",
"id": 10123,
"name": "Q1 Contact"
}
}
}
],
"campaign": {
"id": 1763200,
"name": "Associated campaign name"
},
"from_name": "John Smith",
"from_email": "john@prospect.com",
"recipient": "receiving@email.com",
"mailbox_id": 112233,
"cc": ["steve@prospect.com", "jimothy@prospect.com"],
"not_found": false
}
],
"pagination": {
"previous_page_cursor": null,
"next_page_cursor": "Y3VyaW91cywgYXJlbid0IHlvdT8="
}
}

Body schema

FieldTypeDescription
contentarray[object]Array of email messages
└─[].idintegerUnique ID of the prospect's response
└─[].prospect_idinteger/nullUnique ID of the prospect associated with the response
└─[].global_prospect_statusstring/nullProspect's global status: ACTIVE, BOUNCED, RESPONDED, BLACKLIST, INVALID, OPT_OUT. Available if prospect_id is not null
└─[].readbooleanWhether the message was marked as read
└─[].bouncedbooleanWhehter the message was bounced
└─[].stampstringISO 8601 timestamp of the message in UTC
└─[].subjectstringSubject line of the response
└─[].body.htmlstringBody of the response email in HTML format
└─[].campaignsarray[object]List of campaigns associated with the response. One response can be assigned to multiple campaigns
    └─[].idintegerID of the campaign associated with a response
    └─[].namestringName of the campaign
    └─[].statusstringCurrent status of the campaign. Available values: RUNNING, DRAFT, STOPPED, PAUSED, EDITED, COMPLETED, DELETED
    └─[].prospectobjectCampaign-level prospect information related to this message
        └─campaign_prospect_idintegerID of the campaign prospect. Different than global prospect_id
        └─interest_levelobjectInterest level details for given prospect in associated campaign
            └─levelstringProspect's Interest Level. Available levels: INTERESTED, MAYBE_LATER, NOT_INTERESTED, NOT_MARKED
            └─ai_detectedbooleanIndicates whether the level was set by AI or by the user
        └─statusstringProspect's campaign status: ACTIVE, BOUNCED, RESPONDED, BLACKLIST, OPT_OUT, PAUSED, INVALID, NON_RESPONSIVE. REMOVED
        └─resume_followup_afterstringThe earliest date and time prospects can be contacted, for example to followup after an autoresponder. ISO 8601 timestamp
        └─status_reasonsarray[object]List of reasons clarifying the prospect's status
            └─reasonstringValues can contain: SECONDARY_REPLY, OTHER_CAMPAIGN, AUTOREPLIED, MANUAL, SNIPPET_ISSUE, CATCH_ALL_DELIVERABLE, CATCH_ALL_RISKY, CATCH_ALL_UNDELIVERABLE, ESP_MATCHING
        └─substatusobject/nullDetails about a substatus assigned to a prospect in a campaign. Read more here
            └─idintegerID of the substatus
            └─namestringName of the assigned substatus
            └─created_atstringISO 8601 timestamp of when the substatus was first created
└─[].campaignobjectObject containing a campaign related to the response. Using campaigns instead is recommended.
    └─idinteger/nullID of the campaign associated to a response
    └─namestring/nullName of the campaign
└─[].from_namestringName of the responder
└─[].from_emailstringEmail address of the responder
└─[].recipientstringEmail address of the recipient (typically, the IMAP of the mailbox that sent the email)
└─[].mailbox_idintegerId of the IMAP mailbox that received that message
└─[].ccarray[string]List of email addresses that were added to the CC of the received email
└─[].not_foundbooleanIndicator whether the message content was unavailable to display. If true, try again later
paginationobjectObject containing pagination information
└─next_page_cursorstringPagination cursor. null means no more results (last page); non-null value indicates the cursor for the next page
└─previous_page_cursorstringPagination cursor. null means first page; non-null value indicates the cursor for previous page

Pagination

This endpoint uses cursor-based pagination. Results are returned in pages, and each response includes a next_page_cursor field:

  • To start from the first page, omit the next_page_cursor parameter or set it to null.
  • If next_page_cursor are null, there are no more pages available,
  • If next_page_cursor or previous_page_cursor contain a value, you can use it in the next request to retrieve the next or previous page of results,

Request first page:

curl --request GET \
--url "https://api.woodpecker.co/rest/v2/inbox/messages?prospect_interest_level=INTERESTED" \
--header "x-api-key: {YOUR_API_KEY}"

Example response:

{
"content": [...],
"pagination": {
"next_page_cursor": "T2ggSGkgTWFyayE=",
"previous_page_cursor": null
}
}

Request the next page:

curl --request GET \
--url "https://api.woodpecker.co/rest/v2/inbox/messages?next_page_cursor=T2ggSGkgTWFyayE=&prospect_interest_level=INTERESTED" \
--header "x-api-key: {YOUR_API_KEY}"

Example response:

{
"content": [...],
"pagination": {
"next_page_cursor": "TSXQncyBhIHRyYXAh",
"previous_page_cursor": "RG9uJ3QgdGVsbCBhbnlvbmUh"
}
}

Request the previous page:

curl --request GET \
--url "https://api.woodpecker.co/rest/v2/inbox/messages?next_page_cursor=RG9uJ3QgdGVsbCBhbnlvbmUh&prospect_interest_level=INTERESTED" \
--header "x-api-key: {YOUR_API_KEY}"