Attaching files

Attachments are a two-step building block: upload bytes to POST /api/v1/files, then reference the returned id in a notification's attachments array. A notification can carry up to 16 attachments, each up to 25 MB.

1. Upload the file

curl
curl -X POST "https://api.roundtrip.sh/api/v1/files?filename=quote.pdf" \
  -H "Authorization: Bearer ak_xxx" \
  -H "Content-Type: application/pdf" \
  --data-binary @quote.pdf
SDK
import { readFile } from "node:fs/promises";

const file = await roundtrip.files.upload({
  data: await readFile("quote.pdf"),
  filename: "quote.pdf",
  contentType: "application/pdf",
});

The upload returns:

201 Created
{
  "id": "att_7c12",
  "key": "r2/...",
  "filename": "quote.pdf",
  "contentType": "application/pdf",
  "size": 528412
}

2. Reference it from a notification

curl
curl -X POST https://api.roundtrip.sh/api/v1/notifications \
  -H "Authorization: Bearer ak_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "approvals",
    "push": {
      "title": "Approve $48,200 quote for Acme Corp?",
      "priority": "high"
    },
    "content": {
      "title": "Approve $48,200 quote for Acme Corp?",
      "description": "Net-30 terms. PDF attached.",
      "actions": [
        { "id": "approve", "label": "Approve", "style": "primary" },
        { "id": "reject", "label": "Reject", "style": "destructive" }
      ]
    },
    "attachments": [{ "id": "att_7c12" }],
    "response": {
      "mode": "required",
      "behavior": "resolve",
      "webhook": "https://api.example.com/roundtrip/webhooks"
    },
    "metadata": { "quoteId": "q_0042" }
  }'
SDK
await roundtrip.notify({
  channel: "approvals",
  push: {
    title: "Approve $48,200 quote for Acme Corp?",
    priority: "high",
  },
  content: {
    title: "Approve $48,200 quote for Acme Corp?",
    description: "Net-30 terms. PDF attached.",
    actions: [
      { id: "approve", label: "Approve", style: "primary" },
      { id: "reject", label: "Reject", style: "destructive" },
    ],
  },
  attachments: [{ id: file.id }],
  response: {
    mode: "required",
    behavior: "resolve",
    webhook: "https://api.example.com/roundtrip/webhooks",
  },
  metadata: { quoteId: "q_0042" },
});

Same workspace

The upload and notification must use an API key for the same workspace. The attachment id is scoped to the workspace that uploaded it.

Next steps