Skip to main content
GET
Check Replies
Use this endpoint to check if a specific lead has replied, or to list all leads who replied (optionally scoped to a campaign). Returns the reply text, up to 10 recent replies from the lead, and up to 10 outbound messages you sent them.When a lead replies with a photo or file, the row (and each recentReplies entry) carries attachmentDownloadUrls — public, signed URLs you can GET directly to download the image/file bytes, no auth header needed. See Downloading inbound attachments.

Authentication

Query parameters

string
Replies from this lead only (valid ObjectId; returns 404 if lead not found).
string
Restrict to leads who replied and are in this campaign.
string
Filter by reply sender email.
string
Filter by reply sender phone (E.164 or normalized).
string
Restrict to replies received on this Tuco line (24-char ObjectId hex). Returns 400 if malformed.
string
Inclusive ISO 8601 UTC lower bound on the reply timestamp (e.g. 2026-06-01T00:00:00Z). Returns 400 if unparseable or greater than dateTo.
string
Inclusive ISO 8601 UTC upper bound on the reply timestamp.
number
default:"1"
Page number.
number
default:"50"
Results per page (max 100).

Examples


Success response (200)

Reply fields

string
Lead who replied.
string
ID of the most recent reply message.
string
The reply text (e.g. “Stop”, “Interested!”, “Call me tomorrow”).
string
ISO 8601 timestamp of the most recent reply.
string
Lead’s phone number.
string
Lead’s email address.
string
Lead’s display name.
boolean
true when the lead’s newest inbound is newer than your newest outbound to them (no outbound on record → true). Any follow-up you send after their reply — including AI copilot auto-replies — flips it back to false. With campaignId set, outbounds are scoped to that campaign, so this reads as “replied since the campaign’s last message”.
boolean
Always true for a returned row — leads who never replied have no row. Included so this endpoint and the GHL Check for Replies action expose the same field names; branch on it when an auto-responder makes hasReplied flip to false within seconds.
string[]
Present only when the most recent reply included attachments. Public, signed, 30-day URLs — GET each one (no auth header) to download the actual image/file bytes, served with the correct Content-Type. Omitted for text-only replies. See Downloading inbound attachments.
string[]
Filenames aligned 1:1 with attachmentDownloadUrls (e.g. ["IMG_1380.jpeg"]). Omitted for text-only replies.

recentReplies (up to 10)

All inbound replies from this lead, newest first. Gives you the full conversation context from their side.
array

parentMessages (up to 10)

Outbound messages you sent to this lead, newest first. Shows what you said before they replied.
array

Error responses


Downloading inbound attachments

When a lead replies with a photo or file, Tuco stores the bytes in private blob storage. The raw storage URL is not directly fetchable — it returns 403. Instead, every attachment-bearing reply exposes attachmentDownloadUrls: signed, 30-day proxy URLs that stream the real bytes with the correct Content-Type. You can fetch a download URL with either credential — pick whichever fits:

Just the URL (signature)

The URL already carries an HMAC signature (&sig=…), so no header is needed. Drop it into an <img src>, a re-hosting job, or curl -O. This is the simplest path. The signature is unforgeable and expires after 30 days.

Your API key

Prefer to pass a token? Send Authorization: Bearer tuco_sk_…. Tuco verifies the key’s workspace owns that attachment, so a key can only ever read its own workspace’s files. Revocable by rotating the key.
The signed URL grants read access to that one file for 30 days. Treat it like a capability: fetch and store the bytes in your own system rather than passing the URL around long-term. To fetch a fresh signed URL, just call GET /api/replies (or listen for the message.reply webhook) again.
Download every photo a lead sent
The same attachmentDownloadUrls / attachmentNames fields are delivered in real time on the message.reply webhook and appear on inbound messages from GET /api/messages, so you can ingest photos push-style instead of polling.