API reference
One REST API for Gmail, Microsoft 365 and IMAP. Base URL https://inboxwire.buffersoltech.com/v1. Machine readable: /v1/openapi.json (OpenAPI 3.1).
Authentication, scopes and environments
Send your key as Authorization: Bearer <key>. A key has scopes: read, send (includes read) and admin (includes both). A key without the scope an endpoint needs gets 403 insufficient_scope. Choose the environment with x-environment: development | staging | production; production is the default.
Errors are JSON, {"error":"code"}, with a details field when there is more to say. Each key may make 600 requests a minute; past that you get 429.
Accounts
/v1/accountsList accounts
Mailboxes connected in the key's environment.
Scope: read
curl https://inboxwire.buffersoltech.com/v1/accounts \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}Get an account
State of one mailbox, including the last error and whether it runs on push or polling.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}Delete an account
Stops the provider watch, revokes the token where the provider supports it (Google), deletes the account, its credentials, cursors and queued sends, and writes a `deletion_record` (the address is kept only as a sha256). Needs the admin scope. Message content is never stored, so there is nothing else to remove.
Scope: admin
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl -X DELETE https://inboxwire.buffersoltech.com/v1/accounts/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/usageGet usage
Active mailboxes against the plan: used, included, extra and what the extras cost per month. The dashboard meter shows the same numbers.
Scope: read
curl https://inboxwire.buffersoltech.com/v1/usage \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/connect-linksCreate a connect link
Single-use hosted connect page URL, valid for 24 hours. Opening it a second time returns 410. Needs the admin scope.
Scope: admin
Request body (JSON)
| Name | Type | Notes |
|---|---|---|
| externalId | string | |
| redirectUrl | string (uri) | |
| string (email) |
curl -X POST https://inboxwire.buffersoltech.com/v1/connect-links \
-H "Authorization: Bearer $INBOXWIRE_KEY" \
-H "Content-Type: application/json" \
-d '{}'Read
/v1/accounts/{id}/foldersList folders
Folders (IMAP, Microsoft) or labels (Gmail).
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123/folders \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}/messagesList and search messages
Newest first with cursor pagination. `q` accepts one syntax on every provider (from:, to:, subject:, after:, before:, has:attachment, bare words) and is translated to Gmail `q`, Graph `$filter`/`$search` or IMAP SEARCH.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
Query and headers
| Name | Type | Notes |
|---|---|---|
| q | string | Unified search: from: to: subject: after:YYYY-MM-DD before:YYYY-MM-DD has:attachment, bare words, "quoted phrases". |
| folder | string | Folder id from GET /folders. |
| limit | integer | |
| cursor | string | `nextCursor` from the previous page. |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123/messages \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}/messages/{mid}Get a message
Metadata as JSON, or with `format=raw` the original RFC 822 source (`message/rfc822`). Bodies are fetched from the provider on request and never stored.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string | |
| mid * | string |
Query and headers
| Name | Type | Notes |
|---|---|---|
| format | "json" | "raw" |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123/messages/msg_456 \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}/messages/{mid}/attachmentsList attachments
Attachment metadata of one message.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string | |
| mid * | string |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123/messages/msg_456/attachments \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/accounts/{id}/messages/{mid}/attachments/{aid}Download an attachment
The attachment bytes, always served as a download.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string | |
| mid * | string | |
| aid * | string |
curl https://inboxwire.buffersoltech.com/v1/accounts/acc_123/messages/msg_456/attachments/att_789 \
-H "Authorization: Bearer $INBOXWIRE_KEY"Send
/v1/accounts/{id}/messages/sendSend a message
Queues the message and answers 202 with the outbox id. Gmail and Microsoft send through their APIs, IMAP accounts through the mailbox's SMTP server. Send an `Idempotency-Key` header to make retries safe: for 7 days a repeat returns the original item with `Idempotent-Replayed: true`, and the same key with a different body returns 422.
Scope: send · Causes webhooks: messageSent, messageFailed
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
Query and headers
| Name | Type | Notes |
|---|---|---|
| Idempotency-Key | string | Up to 255 printable ASCII characters. A repeat within 7 days returns the original result. |
curl -X POST https://inboxwire.buffersoltech.com/v1/accounts/acc_123/messages/send \
-H "Authorization: Bearer $INBOXWIRE_KEY" \
-H "Idempotency-Key: order-1042-receipt" \
-H "Content-Type: application/json" \
-d '{"to":[{"address":"ana@example.com"}],"subject":"Hello","text":"Sent through Inboxwire"}'/v1/outbox/{id}Get a queued send
Status of a send: queued, sending, sent or failed.
Scope: read
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl https://inboxwire.buffersoltech.com/v1/outbox/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY"Webhooks
/v1/webhooksList webhook endpoints
Endpoints of the key's environment.
Scope: admin
curl https://inboxwire.buffersoltech.com/v1/webhooks \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/webhooksCreate a webhook endpoint
New endpoints subscribe to `messageNew` unless `events` is given. The response includes the signing secret once. Deliveries carry `Inboxwire-Signature: t=<unix>,v1=<hex>`, the HMAC-SHA256 of `<t>.<raw body>`.
Scope: admin
Request body (JSON)
| Name | Type | Notes |
|---|---|---|
| url * | string (uri) | |
| events | "messageNew" | "messageMoved" | "messageDeleted" | "messageSent" | "messageFailed" | "accountConnected" | "accountInitialized" | "accountError"[] | Event allowlist. Defaults to messageNew. |
curl -X POST https://inboxwire.buffersoltech.com/v1/webhooks \
-H "Authorization: Bearer $INBOXWIRE_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hooks/inboxwire"}'/v1/webhooks/{id}Get a webhook endpoint
One endpoint, including `failingSince` and why it was disabled.
Scope: admin
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl https://inboxwire.buffersoltech.com/v1/webhooks/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/webhooks/{id}Update a webhook endpoint
Change the URL, the event allowlist or `enabled`. Turning a disabled endpoint back on clears its failure clock.
Scope: admin
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
Request body (JSON)
| Name | Type | Notes |
|---|---|---|
| url | string (uri) | |
| events | "messageNew" | "messageMoved" | "messageDeleted" | "messageSent" | "messageFailed" | "accountConnected" | "accountInitialized" | "accountError"[] | |
| enabled | boolean |
curl -X PATCH https://inboxwire.buffersoltech.com/v1/webhooks/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY" \
-H "Content-Type: application/json" \
-d '{}'/v1/webhooks/{id}Delete a webhook endpoint
Stops all deliveries to the endpoint.
Scope: admin
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl -X DELETE https://inboxwire.buffersoltech.com/v1/webhooks/acc_123 \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/deliveriesList deliveries
The delivery log: status, attempts, status code, latency and the start of the response of the last attempt. Failed deliveries retry with backoff for about 24 hours; an endpoint failing for 72 hours is disabled and the owners are emailed.
Scope: admin
Query and headers
| Name | Type | Notes |
|---|---|---|
| endpointId | string | |
| status | "pending" | "succeeded" | "failed" | "retrying" | |
| limit | integer |
curl https://inboxwire.buffersoltech.com/v1/deliveries \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/deliveries/{id}/replayReplay a delivery
Sends the stored payload again as a new delivery with the same event id. 409 when the endpoint is disabled.
Scope: admin
Path parameters
| Name | Type | Notes |
|---|---|---|
| id * | string |
curl -X POST https://inboxwire.buffersoltech.com/v1/deliveries/acc_123/replay \
-H "Authorization: Bearer $INBOXWIRE_KEY"/v1/deliveries/replayReplay failed deliveries
Bulk replay of failed deliveries that were not replayed yet, optionally for one endpoint.
Scope: admin
Request body (JSON)
| Name | Type | Notes |
|---|---|---|
| endpointId | string | |
| limit | integer |
curl -X POST https://inboxwire.buffersoltech.com/v1/deliveries/replay \
-H "Authorization: Bearer $INBOXWIRE_KEY" \
-H "Content-Type: application/json" \
-d '{}'Webhook events and signatures
Events are POSTed as JSON {"id","type","created","data"}. The id stays the same on retries and replays, so use it to dedupe. Return any 2xx within 10 seconds; otherwise we retry with backoff for about 24 hours. After 72 hours of failures the endpoint is disabled and the owners get an email. Failed events stay in the delivery log and can be replayed.
Verify every request: compute HMAC-SHA256 of <t>.<raw body> with your endpoint secret and compare it to v1 in the Inboxwire-Signature header. Reject timestamps older than five minutes.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, rawBody, header) {
const p = Object.fromEntries(header.split(",").map((x) => x.split("=")));
if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
const mac = createHmac("sha256", secret).update(p.t + "." + rawBody).digest();
const given = Buffer.from(p.v1, "hex");
return given.length === mac.length && timingSafeEqual(given, mac);
}Events
| Name | Type | Notes |
|---|---|---|
| messageNew | event | A message arrived. The default for new endpoints. |
| messageMoved | event | Labels or folder changed. |
| messageDeleted | event | A message was deleted. |
| messageSent | event | A queued send went out. |
| messageFailed | event | A queued send failed for good. |
| accountConnected | event | A mailbox was connected. |
| accountInitialized | event | History was reset; resync if you track state. |
| accountError | event | The mailbox needs attention. |