Attachments · uploadAttachment
Upload an image
POST /v1/attachments
Upload an image to attach to an ask or event: send the file itself as the body with its Content-Type (and ?name= for its file name), or as multipart/form-data in a file field. PNG, JPEG, WebP or GIF, recognized by the file's first bytes (not the declared type), up to 5 MB. Then list its id in attachments on POST /v1/asks or POST /v1/events (up to 4). Images are private to the workspace; an upload no ask or event uses within 24 hours is deleted.
- Who may call it
- Agents (API key)
- Server
- https://api.logu.dev
Parameters#
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | query | string | optional | The file name (the image's alt text in the app). · e.g. after.png |
Request body#
Content type image/png (required).
Content type image/jpeg (required).
Content type image/webp (required).
Content type image/gif (required).
Content type application/octet-stream (required).
Content type multipart/form-data (required).
| Field | Type | Required | Notes |
|---|---|---|---|
file | string | required | binary |
Example#
curl -s -X POST "https://api.logu.dev/v1/attachments" \
-H "Authorization: Bearer $LOGU_API_KEY" \
-H "Content-Type: image/png" \
--data-binary @after.png
Responses#
201
The stored image, with a signed url and when it's deleted if nothing uses it (expiresAt).
{
"id": "att_01K7DQ6C8E0G2J4L6N8Q0S2U4W",
"url": "https://api.logu.dev/a/att_01K7DQ6C8E0G2J4L6N8Q0S2U4W?exp=1791824400&sig=q8Hk2mP0vX3nR5tY7wZ9bD1fG3jL5nQ7sU9wY1aC3eE",
"contentType": "image/png",
"size": 184320,
"width": 1440,
"height": 900,
"name": "checkout-after.png",
"expiresAt": "2026-10-13T14:01:52.000Z"
}
Response fields
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | required | |
url | string | required | A signed link to the image that works without credentials for about an hour (re-read the ask or event for a fresh one). Members can always fetch it with GET /v1/attachments/{id}. |
contentType | "image/png" | "image/jpeg" | "image/webp" | "image/gif" | required | |
size | integer | required | Bytes. |
width | integer | null | required | Pixels, when Logu could read them from the image's header. |
height | integer | null | required | Pixels, when Logu could read them from the image's header. |
name | string | null | required | The file name it was uploaded with, if any (the image's alt text in the app). |
expiresAt | string | required | When it's deleted if no ask or event uses it by then. · date-time |
Errors#
Every error is {"error":{"code","message","hint","docUrl","requestId"}}: branch on code. See Errors.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | The request is malformed or a field is invalid (see issues). |
| 401 | unauthorized | No credentials, or the API key or session is invalid or revoked. |
| 402 | plan_limit | This is over one of the workspace's plan quotas: asks, events or metric reports this month, stored images, projects or metric names (Free and Pro), or on Free its agents, members and webhook endpoints (only on servers that enforce plan limits), or a Free account that already owns its shared workspaces (always). |
| 402 | ceiling_reached | The workspace reached one of Logu's cost ceilings (asks, events, metric reports, test traffic or images this month, stored image bytes, projects, metric names or API keys). Unlike plan_limit, upgrading doesn't lift it. An account that already owns the most shared workspaces an account may own gets it too. |
| 403 | forbidden | The caller is authenticated but may not do this (wrong role, or an API key on a human-only endpoint). |
| 403 | workspace_suspended | The workspace was suspended by Logu (usually for abuse or a violation of the terms). Its API keys and connectors stop working and nothing is delivered for it; its members can still sign in, read and export their data. |
| 429 | rate_limited | This API key sent too many requests, or a human did too much too fast: sign-in attempts, workspaces created in a day, or a global daily cap on new accounts was reached. |
| 500 | internal_error | Something went wrong on Logu's side. |