When the assistant decides an action from your app should run, Orceum constructs and sends an authenticated HTTP request to your base_url + the action’s endpoint. Your job is to handle it, execute the work, and return a clean response.

Request Format

Orceum always sends a POST request regardless of your action’s method field (the method is used for OpenAPI generation and display purposes). The request body is JSON:
{
  "event": "create_task",
  "event_data": {
    "title": "Send Q4 report",
    "due_date": "2024-12-31"
  },
  "timestamp": "2024-01-15T12:00:00Z"
}
FieldTypeDescription
eventstringThe action name from your manifest (e.g. create_task)
event_dataobjectThe parameter values resolved by the assistant
timestampstringISO 8601 UTC timestamp of when the call was made

Request Headers

Every action call includes these headers:
POST /actions HTTP/1.1
Host: todo.yourapp.com
Content-Type: application/json
Authorization: Bearer sk-user-api-key       # (API_KEY auth)
X-Orceum-Installation-Id: inst_abc123
X-Request-ID: req_xyz789
X-Timestamp: 2024-01-15T12:00:00Z
X-Orceum-Installation-Id identifies which user’s installation triggered this call. Use this to look up the correct user record in your database. Every user has a unique installation ID — don’t treat all calls as coming from the same account.

Auth Headers by Type

No credential headers injected. Your app receives only the standard headers above.

Additional Headers and Query Params

You can configure static headers or query parameters to be appended to all action calls in the Orceum Developer Studio under your app’s settings. For example, you might add:
  • Additional Headers: X-App-Version: 2.0, X-Service-Region: eu-west-1
  • Additional Query Params: format=json, version=2
These are merged with every request, alongside the user’s credential headers.

Routing Actions

If all your actions share a single endpoint (e.g. POST /actions), use event to route:
from fastapi import FastAPI, Request, Header
from typing import Optional

app = FastAPI()

@app.post("/actions")
async def handle_action(
    request: Request,
    x_orceum_installation_id: Optional[str] = Header(None)
):
    body = await request.json()
    event = body.get("event")
    event_data = body.get("event_data", {})
    installation_id = x_orceum_installation_id

    if event == "create_task":
        return await create_task(installation_id, event_data)
    elif event == "list_tasks":
        return await list_tasks(installation_id, event_data)
    elif event == "delete_task":
        return await delete_task(installation_id, event_data)
    else:
        return {"error": f"Unknown action: {event}"}, 400

Response Format

Your action must return a JSON object with a top-level result key.
{
  "result": {
    "task_id": "task_789",
    "title": "Send Q4 report",
    "due_date": "2024-12-31",
    "status": "created"
  }
}

Flexible Schema (Any Valid JSON)

Orceum does not enforce a strict schema for what goes inside the result key. The result value can be any valid JSON: an object, an array of items, a simple string, or a number. The Orceum AI simply reads whatever raw JSON data you return and uses it as context to formulate a natural, conversational response for the user. You do not need to format your data into human-readable strings. Return raw structured data (like IDs, timestamps, and status codes), and let the AI do the work of explaining it to the user.

For long-running operations

If your action takes more than a few seconds, return immediately with a reference, then push a webhook event when complete:
{
  "result": {
    "task_id": "task_789",
    "status": "processing",
    "message": "Export started. You'll be notified when it's ready."
  }
}
Then send a webhook event when done. See Webhooks.

Timeout

Orceum waits 30 seconds for a response. If your endpoint doesn’t respond within that window, the call is marked as failed and the user receives an error message. For operations that take longer, always use the async pattern above.