LoguDocs
Open Logu

Asks · listAsks

List asks

GET /v1/asks

The workspace's asks, newest first (asks created in the same millisecond keep one order). Page with cursor: pass the previous page's nextCursor until it is null. before (the last id of the previous page) still works. An invalid cursor is a 400 (bad_request).

Who may call it
Agents (API key); humans: every member
Server
https://api.logu.dev

Parameters#

NameInTypeRequiredDescription
limitqueryintegeroptionalHow many to return (1–100). · e.g. 50
statusquery"waiting" | "decided" | "timed_out" | "withdrawn"optionalOnly asks in this state (waiting for the ones still open). · e.g. waiting
beforequerystringoptionalThe last ask id of the previous page (asks are newest first). Prefer cursor; not with it. · e.g. ask_01K7DQ3M2V8H4N6R9T1W3Y5B7C
cursorquerystringoptionalWhere this page starts: the nextCursor of the previous page, unchanged. Leave it out (or empty) for the first page. · e.g. YXNrczoxNzkxODEzNzkxMDAwOmFza18wMUs3RFEzTTJWOEg0TjZSOVQxVzNZNUI3Qw
Logu-WorkspaceheaderstringoptionalHumans only: the workspace to act in (default: your personal workspace). Agents always act in their API key's workspace. · e.g. wsp_01K7D7Y8Z0B2D4F6H8K0M2P4R6

Example#

curl -s "https://api.logu.dev/v1/asks" \
  -H "Authorization: Bearer $LOGU_API_KEY"

Responses#

200

Asks, newest first, and where the next page starts (null at the end).

{
  "asks": [
    {
      "id": "ask_01K7DQ3M2V8H4N6R9T1W3Y5B7C",
      "project": "shop",
      "channel": null,
      "title": "Deploy v1.4 to production?",
      "body": "3 commits since v1.3. CI is green.",
      "icon": null,
      "url": "https://github.com/acme/shop/compare/v1.3...v1.4",
      "options": [
        {
          "id": "approve",
          "label": "Approve",
          "style": "primary"
        },
        {
          "id": "decline",
          "label": "Decline",
          "style": "danger"
        }
      ],
      "allowText": false,
      "status": "waiting",
      "decision": null,
      "defaultOption": "decline",
      "expiresAt": "2026-10-12T15:03:11.000Z",
      "createdAt": "2026-10-12T14:03:11.000Z",
      "metadata": null,
      "agent": {
        "id": "agt_01K7D8F2H4K6M8P0R2T4V6X8Z0",
        "name": "deploy-bot"
      },
      "attachments": [
        {
          "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"
        }
      ],
      "test": false
    }
  ],
  "nextCursor": "YXNrczoxNzkxODEzNzkxMDAwOmFza18wMUs3RFEzTTJWOEg0TjZSOVQxVzNZNUI3Qw"
}
Response fields
FieldTypeRequiredNotes
asksAsk[]required
asks[].idstringrequired
asks[].projectstringrequired
asks[].channelstring | nullrequired
asks[].titlestringrequired
asks[].bodystring | nullrequired
asks[].iconstring | nullrequired
asks[].urlstring | nullrequired
asks[].optionsAskOption[]required
asks[].options[].idstringrequired1–64 chars · pattern ^[a-z0-9][a-z0-9._-]*$
asks[].options[].labelstringrequired1–64 chars
asks[].options[].style"primary" | "danger" | "default"required
asks[].allowTextbooleanrequired
asks[].status"waiting" | "decided" | "timed_out" | "withdrawn"required
asks[].decisionDecision | nullrequired
asks[].decision.optionIdstring | nullrequired
asks[].decision.textstring | nullrequired
asks[].decision.decidedVia"app" | "link" | "telegram" | "slack" | "whatsapp" | "rule" | "timeout"required
asks[].decision.decidedAtstringrequireddate-time
asks[].decision.decidedByMemberRef | nullrequired
asks[].decision.ruleIdstring | nulloptional
asks[].defaultOptionstring | nulloptionalApplied as the decision if nobody decides before expiresAt (then decision.decidedVia is timeout: never an approval); null: it ends timed_out. Agents can't set an approving one (id approve or style primary) on new asks.
asks[].expiresAtstringrequireddate-time
asks[].createdAtstringrequireddate-time
asks[].metadataobject | nullrequiredFree-form context stored with the item, up to 8,192 characters of JSON. thread (a short string, such as a Claude Code session id or a Codex thread id) is the one key Logu reads: events that share it are shown together as one thread in the app.
asks[].agentAgentRef | nullrequired
asks[].agent.idstringrequired
asks[].agent.namestringrequired
asks[].attachmentsAttachment[]requiredIts images, in order, each with a signed url that works for about an hour.
asks[].attachments[].idstringrequired
asks[].attachments[].urlstringrequiredA 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}.
asks[].attachments[].contentType"image/png" | "image/jpeg" | "image/webp" | "image/gif"required
asks[].attachments[].sizeintegerrequiredBytes.
asks[].attachments[].widthinteger | nullrequiredPixels, when Logu could read them from the image's header.
asks[].attachments[].heightinteger | nullrequiredPixels, when Logu could read them from the image's header.
asks[].attachments[].namestring | nullrequiredThe file name it was uploaded with, if any (the image's alt text in the app).
asks[].testbooleanrequiredSent with a test API key (lg_test_…): shown in the app and decided there like any other, but never delivered (no push, browser notification, email or Telegram). Its callback is sent.
asks[].escalationobject | nulloptional
asks[].escalation.atstringrequireddate-time
asks[].escalation.toMemberRef[]required
nextCursorstring | nullrequiredPass as cursor for the next page, unchanged; null at the end of the list.

Errors#

Every error is {"error":{"code","message","hint","docUrl","requestId"}}: branch on code. See Errors.

StatusCodeMeaning
400bad_requestThe request is malformed or a field is invalid (see issues).
401unauthorizedNo credentials, or the API key or session is invalid or revoked.
403forbiddenThe caller is authenticated but may not do this (wrong role, or an API key on a human-only endpoint).
403workspace_suspendedThe 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.
404not_foundNo such route, or the resource doesn't exist in your workspace.
429rate_limitedThis 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.
500internal_errorSomething went wrong on Logu's side.