Answer an approval

October 12, 2026

Table of contents

  1. Request Headers
  2. Request Body
  3. Responses
  4. Model
  5. Examples
  6. Try It

Before some actions, for example sending information to a website while it runs code, the Muse agent asks for your permission. The question arrives on GET /chats/chatId/stream as an approval event, and GET /chats/chatId lists the open ones in pendingApprovals. This endpoint gives your answer.

While a request waits, the answer is paused: the stream shows a status event pending_user_confirmation, and no turn.done comes. After your answer, the stream shows approval.resolved, and the agent goes on.

  • allow_once allows this one request.
  • allow_always allows the site from now on, for the whole Muse account. It is Muse’s own “Always allow this site” and stays in place.
  • deny refuses the request. The agent goes on without it.

A request that is not answered by its expires time ends as timed out.

https://api.useapi.net/v1/muse/chats/chatId/approvals/approvalId

  • chatId is URL-encoded in the path (it contains : and @).
  • approvalId is the approvalId of the approval event.
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
Request Body
{
  "decision": "allow_once"
}
  • decision is required, one of the decision values in the request’s options, usually allow_once, allow_always or deny.

An approval event looks like this:

{
  "event": "approval",
  "approvalId": "87c8850c-5c3e-49be-b4d8-981d7fe31952",
  "title": "Share info with deb.nodesource.com",
  "question": "Allow Muse to share information with deb.nodesource.com?",
  "details": [
    { "label": "Host", "value": "deb.nodesource.com" },
    { "label": "Grants", "value": "nodesource.com and all subdomains" },
    { "label": "Method", "value": "CONNECT" },
    { "label": "Path", "value": "deb.nodesource.com:443" },
    { "label": "Policy", "value": "tool.exec" }
  ],
  "options": [
    { "decision": "allow_once", "label": "Allow once" },
    { "decision": "allow_always", "label": "Always allow this site" },
    { "decision": "deny", "label": "Deny" }
  ],
  "expires": "2026-10-13T00:42:04.519Z"
}
Responses
  • 200 OK — Muse took the answer. status is approved or denied, or decided when Muse does not say.

    {
      "chatId": "c-u12345-email:[email protected]:e72e976b-1e33-4406-b8ae-e2980040e9f9-bot:muse",
      "approvalId": "87c8850c-5c3e-49be-b4d8-981d7fe31952",
      "decision": "allow_once",
      "status": "approved"
    }
    
  • 400 Bad Request — decision is missing or is not one of the request’s options, or a path value is invalid.

    {
      "error": "decision must be one of allow_once, allow_always, deny",
      "code": 400
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "useapi.net ⁝ Unauthorized",
      "code": 401
    }
    
  • 403 Forbidden — the chatId was issued to a different API token.

    {
      "error": "This chat id does not belong to this API token",
      "code": 403
    }
    
  • 404 Not Found — this chat has no request with this approvalId, or the account that holds the chat is not added.

    {
      "error": "Approval not found for this chat",
      "code": 404
    }
    
  • 409 Conflict — the request is no longer waiting: it was already answered, or it timed out.

    {
      "error": "This approval is no longer waiting (status approved, decision allow_once)",
      "code": 409
    }
    
  • 502 Bad Gateway — Muse did not take the answer. Retry while the request is still waiting.

  • 503 Service Unavailable — Muse could not be reached. Retry shortly.

  • 596 Account Error

    The account needs your attention, and it is paused until you add it again. You receive an email when this happens. There are two causes.

    Meta asks for a security check on the account. Sign in once at muse.ai in a browser, complete the check, then add the account again with POST /accounts using the same email and password. The API keeps using its session, so no new sign-in is needed.

    {
      "error": "Account [email protected]: Meta asks for a security check on account [email protected] (\"This account must complete a security checkpoint on the web\"). Sign in once at https://muse.ai in a browser, complete the check, then add the account again with POST /accounts",
      "code": 596
    }
    

    Or Muse refused to sign the account in again when its session needed renewing, most often because the password was changed. Add the account again with the current password.

    {
      "error": "Account [email protected]: Muse refused to sign in account [email protected] (…). Update its password with POST /accounts, or sign in at https://muse.ai to clear the block, then re-add it",
      "code": 596
    }
    
Model
{ // TypeScript, all fields are optional
  chatId: string
  approvalId: string
  decision: string            // the decision you sent
  status: string              // approved or denied, or decided when Muse does not say
  error?: string              // errors only
  code?: number               // errors only
}
Examples
  • CHATID="c-u12345-email:[email protected]:e72e976b-1e33-4406-b8ae-e2980040e9f9-bot:muse"
    APPROVALID="87c8850c-5c3e-49be-b4d8-981d7fe31952"
    curl -X POST "https://api.useapi.net/v1/muse/chats/$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1],safe=''))" "$CHATID")/approvals/$APPROVALID" \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer …" \
       -d '{"decision": "allow_once"}'
    
  • const token = "API token";
    const chatId = "chatId from POST /chats";
    const approvalId = "approvalId from the approval event";
    const apiUrl = `https://api.useapi.net/v1/muse/chats/${encodeURIComponent(chatId)}/approvals/${encodeURIComponent(approvalId)}`;
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`,
      },
      body: JSON.stringify({ decision: "allow_once" })
    });
    console.log("response", response.status, await response.json());
    
  • import requests
    from urllib.parse import quote
    token = "API token"
    chatId = "chatId from POST /chats"
    approvalId = "approvalId from the approval event"
    apiUrl = f"https://api.useapi.net/v1/muse/chats/{quote(chatId, safe='')}/approvals/{quote(approvalId, safe='')}"
    headers = {
        "Content-Type": "application/json",
        "Authorization" : f"Bearer {token}"
    }
    response = requests.post(apiUrl, headers=headers, json={"decision": "allow_once"})
    print(response, response.json())
    
Try It