Skip to content

API

The Yamidoo API gives your own code, and AI assistants you run, the same view of a project as the dashboard: its conversations, analytics and content gaps, plus write access to the hand-written parts of its knowledge base. A typical use is a weekly routine that reads last week’s chats and the questions the AI couldn’t answer, then adds Q&A or a doc article to close the gaps.

Available on the Plus and Pro plans.

In the dashboard open your project → Integrations → API and click Create key. The key is shown once; store it somewhere safe. A site can have up to 5 active keys, and you can revoke any of them at any time.

Keys belong to one project. Every endpoint reads and writes that project only; there is no cross-project access.

https://app.yamidoo.ai/api/v1/…
Authorization: Bearer yk_live_…
Content-Type: application/json
  • Times are ISO 8601 in UTC. Query parameters that take a time (since, until, before) accept any ISO date or date-time.
  • Lists are newest first. When a list has more, the response includes next_cursor; pass it as before to get the next page.
  • Errors come back as { "error": "…" } with a matching status code, and details when a field failed validation.
  • Visitor names and emails are included where the dashboard shows them. Keep keys on your server; never put one in a browser.
Endpoint What it does
GET /conversations List conversations, optionally with transcripts.
GET /conversations/:id One conversation with its transcript.
GET /analytics The Analytics page’s numbers for a period.
GET /content-gaps Questions the AI couldn’t answer well.
GET /content-gaps/topics Those questions grouped into topics.
PATCH /content-gaps/:id Mark a gap solved or ignored.
GET /sources Every source the AI answers from.
GET /sources/:id One source; text sources include their content.
POST /sources Add a text source.
PATCH /sources/:id Edit a text source.
POST /sources/:id/sync Re-sync a sitemap, crawl, URL-list or file source.
GET /qa The Q&A pairs.
POST /qa Add Q&A pairs.
PATCH /qa/:id, DELETE /qa/:id Edit or remove a pair.
POST /draft Draft a reply to a customer’s email.
Parameter Description
since, until Only conversations started in this window.
status ai, waiting_human, with_agent or closed.
placement floating, inline or iframe: where the chat was installed.
placement_label Your data-placement label, e.g. contact.
tag A tag name, as shown in the inbox.
rated=true Only conversations the visitor rated.
include=messages Embed each conversation’s transcript. Limit is then 50 per page.
limit 1 to 200, default 50.
before The next_cursor from the previous page.
Terminal window
curl "https://app.yamidoo.ai/api/v1/conversations?since=2026-10-01&include=messages" \
-H "Authorization: Bearer yk_live_…"
{
"conversations": [
{
"id": "77b4d6ae-…",
"status": "closed",
"created_at": "2026-10-06T13:34:11Z",
"last_message_at": "2026-10-06T13:41:02Z",
"ended_by": "visitor",
"ended_at": "2026-10-06T13:41:02Z",
"rating": 4,
"human_involved": false,
"placement": "inline",
"placement_label": "contact",
"start_page": "https://example.com/contact/",
"visitor": { "name": "Jane", "email": "jane@example.com", "email_verified": false, "country": "DE", "country_name": "Germany" },
"tags": ["refund"],
"message_count": 6,
"messages": [
{ "id": "…", "role": "visitor", "content": "Can I get a refund?", "created_at": "…", "rating": null, "rating_reason": null, "confidence": null, "answer_status": null, "sources": [], "has_attachments": false },
{ "id": "…", "role": "ai", "content": "Yes, within 14 days of purchase. …", "created_at": "…", "rating": 1, "rating_reason": null, "confidence": 0.81, "answer_status": "answered", "sources": [{ "title": "Refund policy", "url": "https://example.com/refunds/" }], "has_attachments": false }
]
}
],
"next_cursor": "2026-10-05T09:12:00Z"
}

Message roles are visitor, ai, agent (a teammate) and system (notes such as “Our team is away right now”). On AI messages, rating is the visitor’s thumbs (1 or -1), rating_reason the reason after a thumbs-down (wrong, incomplete, outdated), confidence the retrieval match from 0 to 1, and answer_status the classifier’s verdict: answered, partial, unanswered or not_question.

human_involved is true when a teammate replied in the chat; ended_by is agent, visitor or auto (closed for inactivity).

One conversation in the same shape, always with messages.

Parameter Description
days 1 to 365, default 30.
since, until An explicit window instead of days.
{
"period": { "since": "2026-09-07T00:00:00Z", "until": "2026-10-07T00:00:00Z" },
"conversations": 37,
"messages": 122,
"visitor_messages": 52,
"ai_messages": 36,
"handoffs": 9,
"handoff_rate": 24.3,
"avg_ai_response_seconds": 4.9,
"csat": { "average": 4.3, "ai_only": 4.1, "with_team": 4.8, "ratings": 12 },
"helpful_answers": { "rate": 83.3, "rated": 18 },
"by_status": { "closed": 35, "waiting_human": 2 },
"by_ended_by": { "visitor": 19, "agent": 7, "auto": 6 },
"by_placement": {
"floating": { "conversations": 30, "labels": {} },
"inline": { "conversations": 7, "labels": { "contact": 7 } }
}
}

Rates are percentages. csat is the average of the 1 to 5 conversation ratings, split into chats the AI handled alone and chats a teammate replied in. helpful_answers.rate is the share of rated AI answers that got a thumbs up. The figures cover up to 10,000 conversations in the period; truncated: true tells you when a period had more.

Each item is an AI answer that was classified unanswered or partial, or that the visitor rated thumbs-down, together with the question that preceded it. These are the same items as the dashboard’s Content gaps page.

Parameter Description
status open (default) or resolved.
kind unanswered, partial or downvoted.
since Only answers given after this time.
limit, before Paging, as for conversations.
{
"gaps": [
{
"id": "889ee91e-…",
"conversation_id": "a1698b35-…",
"kind": "unanswered",
"question": "Can I use the theme on a staging site without a second license?",
"answer": "I don't have information about staging sites in the content I have. …",
"answer_status": "unanswered",
"rating": null,
"rating_reason": null,
"confidence": 0.31,
"sources": [],
"resolution": null,
"resolved_at": null,
"created_at": "2026-10-05T08:40:50Z"
}
],
"next_cursor": null
}

The open gaps grouped into topics by the periodic rebuild, with the dashboard’s suggested question and outline for each, counts by kind, and last_7_days versus previous_7_days for the trend. computed_at says when the grouping last ran.

{ "resolution": "solved" }

solved or ignored removes the gap from the open list and from topics; null restores it. When your script adds a Q&A pair that answers a gap, mark the gap solved in the same run.

Every source, newest first: id, type (sitemap, website_crawl, url_list, file, text or qa), title, status (pending, processing, ready or error), pages indexed, error, last_synced_at and refresh. Sitemap, crawl and URL-list sources also include their url or urls and patterns; Q&A sources the number of pairs.

One source. Text sources include content.

Add a text source: plain text or Markdown, indexed right away. Use it for doc articles, policies or notes the AI should answer from.

{ "type": "text", "title": "Staging sites", "content": "# Staging sites\n\nYou can use your license on a staging site …" }

title is optional; the first line is used when it’s missing. content is up to 200,000 characters. Returns the source and the number of chunks indexed. Other source types are added from the dashboard, where you can scan a sitemap and choose sections.

Change a text source’s title or content. The source is re-indexed. Only text sources can be edited through the API.

Re-sync a sitemap, crawl, URL-list or file source in the background, the same as the dashboard’s re-sync button. Returns 202 with queued: true, or queued: false when a sync is already running. Text and Q&A sources are indexed when saved and return 400.

Hand-written questions and answers, which the AI treats as authoritative over crawled pages. A project can have up to 500 pairs.

{ "pairs": [ { "id": "583f6d74-…", "question": "How many sites can I use a theme on?", "answer": "As many as you like. …" } ] }
{ "pairs": [ { "question": "…", "answer": "…" } ] }

Adds the pairs (1 to 200 per call) and keeps the existing ones. Returns the added pairs with their ids and the new total. The whole list is re-indexed on every write, so batch additions into one call.

PATCH /api/v1/qa/:id and DELETE /api/v1/qa/:id

Section titled “PATCH /api/v1/qa/:id and DELETE /api/v1/qa/:id”

Change a pair’s question or answer, or remove it.

Send a customer’s message, get back a reply drafted the way the widget would answer it. Nothing is sent to the customer: you decide what to do with the draft, whether that’s pasting it into Help Scout, showing it to an agent, or sending it from your own code. Each request counts as one conversation, the same as a chat.

POST https://app.yamidoo.ai/api/v1/draft
Authorization: Bearer yk_live_…
Content-Type: application/json
Field Type Description
message string Required. The customer’s latest message, the one to reply to. Up to 12,000 characters.
subject string The email subject, if there is one. Gives the draft context.
history array Earlier turns of the thread, oldest first, as { "role": "customer" | "agent", "content": "…" }. Up to 20.
customer.name string The customer’s name. Used sparingly in the draft.
customer.email string The customer’s email. With a store connected under Integrations → Customer data, and the AI switch on, the draft can use their orders, licenses and subscriptions.
Terminal window
curl https://app.yamidoo.ai/api/v1/draft \
-H "Authorization: Bearer yk_live_…" \
-H "Content-Type: application/json" \
-d '{
"subject": "License question",
"message": "Hi, when does my license expire and can I still get updates?",
"customer": { "name": "Jane", "email": "jane@example.com" }
}'
{
"needs_reply": true,
"skip_reason": null,
"draft": "Hi Jane,\n\nYour Inspiro license runs until 14 March 2027, so you'll keep getting updates until then. …\n\nBest regards,\nThe WPZOOM team",
"sources": [
{ "title": "License renewals – WPZOOM", "url": "https://www.wpzoom.com/docs/renewals/" }
],
"grounded": true,
"confidence": 0.82,
"needs_human": false,
"customer_data_used": true,
"model": "claude-sonnet-5"
}
Field Description
needs_reply false when the message should not get a reply: a bounce notice, an auto-reply, a newsletter, a system notification or spam. draft is empty then and skip_reason says why.
skip_reason A few words on why no reply was drafted, or null.
draft Empty when needs_reply is false. Otherwise the reply, written as a complete email: a greeting (Hi Jane, or Hi there,), the answer, and Best regards, signed with your site name. First person as your team, light Markdown (bold, lists, links).
sources The pages the draft was answered from. Show them to the agent, or leave them out of the reply.
grounded true when relevant content was found. false means the draft could not be answered from your site.
confidence How well your content matched the question, from 0 to 1.
needs_human true when the draft isn’t grounded or confidence is low. Treat these as “read before sending”.
customer_data_used true when the customer’s account data was included.
model The model that wrote the draft. Depends on your plan.

The draft follows the same rules as the widget: it answers from your content, quotes prices and figures exactly, and says when it doesn’t have the answer rather than guessing. Custom instructions under Settings → Behavior apply here too.

Status Meaning
400 A parameter or body field is invalid. The response names it.
401 Missing, invalid or revoked API key.
402 The plan’s limit is reached: monthly conversations (drafts) or indexed pages (sources).
403 The site’s plan doesn’t include the API.
404 No such conversation, source, pair or gap in this project.
429 Rate limit hit for this key. Retry after a minute.
503 Drafting is temporarily unavailable. Retry.

Per key, per minute: 120 reads, 30 source writes, 10 Q&A writes and 60 drafts. Reading data is free; each draft counts as one conversation against the plan, and sources and Q&A count toward the plan’s indexed pages like anything added in the dashboard.

Using Help Scout? The built-in Help Scout integration does this for you, with no code. The script below is for when you want to run it yourself.

A small script that runs when a new conversation arrives, drafts a reply and saves it as a note so the agent sees it before replying:

const res = await fetch('https://app.yamidoo.ai/api/v1/draft', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.YAMIDOO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
subject: conversation.subject,
message: latestCustomerMessage.text,
history: earlierThreads.map((t) => ({
role: t.createdBy.type === 'customer' ? 'customer' : 'agent',
content: t.text,
})),
customer: { name: conversation.customer.firstName, email: conversation.customer.email },
}),
});
const { draft, needs_human, sources } = await res.json();
await helpscout.addNote(conversation.id, [
needs_human ? '⚠️ Low confidence — check before sending.' : '',
draft,
sources.length ? '\nSources: ' + sources.map((s) => s.url).join(', ') : '',
].join('\n'));