Как избежать повторной отправки?

Идемпотентность и учёт состояния.

Ретраи из-за сети или багов могут отправить одно письмо дважды. Ниже — как это предотвратить.

Создание ресурсов: clientId

Для create (ящики, pod, webhook, черновики) передайте clientId: если ресурс уже есть, API вернёт его, а не создаст дубликат.

TypeScript
1import { AgentinboxClient } from "agentinbox";
2
3const client = new AgentinboxClient({ apiKey: "am_..." });
4
5const inbox = await client.inboxes.create({
6 username: "support",
7 clientId: "support-inbox-v1",
8});
9
10const sameInbox = await client.inboxes.create({
11 username: "support",
12 clientId: "support-inbox-v1",
13});

Отправка писем: не через clientId на send

messages.send без встроенной идемпотентности ключа — логика в приложении.

Метки как состояние

TypeScript
1const threads = await client.inboxes.threads.list(inbox.inboxId, {
2 labels: ["unreplied"],
3});
4
5for (const thread of threads.threads) {
6 const detail = await client.threads.get(thread.threadId);
7 const lastMessage = detail.messages[detail.messages.length - 1];
8
9 await client.inboxes.messages.reply(inbox.inboxId, lastMessage.messageId, {
10 text: "Thanks for reaching out!",
11 });
12
13 await client.inboxes.messages.update(inbox.inboxId, lastMessage.messageId, {
14 addLabels: ["replied"],
15 removeLabels: ["unreplied"],
16 });
17}

Черновики для критичных писем

TypeScript
1const draft = await client.inboxes.drafts.create(inbox.inboxId, {
2 to: ["customer@example.com"],
3 subject: "Order confirmation",
4 text: "Your order has been confirmed.",
5 html: "<p>Your order has been confirmed.</p>",
6 clientId: "order-123-confirmation",
7});
8
9const sent = await client.inboxes.drafts.send(inbox.inboxId, draft.draftId);

После отправки черновик удаляется — повторный send не продублирует письмо.

Практика

  • clientId на всех create из бизнес-логики (order-${id}-...), не случайный UUID
  • Метки против двойной обработки одного сообщения
  • Черновики там, где дубликат недопустим

Подробнее: Идемпотентность.