Understanding Orceum’s retry and timeout behavior helps you design resilient apps that handle edge cases gracefully.

Timeout

Orceum waits 30 seconds for a response from your app’s endpoint. If your endpoint does not respond within this window:
  • The action call is marked as failed
  • The user receives an error message
  • No retry is attempted for timeout failures (distinct from 429 retries)

Design for the 30-Second Limit

Most operations complete well within this limit. But some are unpredictably slow:
  • File processing / exports
  • Multi-step external API calls
  • AI/ML inference pipelines
  • Database report generation
For these, return immediately and process asynchronously:
@app.post("/actions")
async def handle_action(request: Request):
    body = await request.json()
    event = body["event"]

    if event == "generate_report":
        task_id = await enqueue_report_job(body["event_data"])

        # Return immediately — don't wait for the job
        return {
            "result": {
                "task_id": task_id,
                "status": "processing",
                "message": "Your report is being generated. I'll notify you when it's ready."
            }
        }
Then push a webhook event when the job completes:
async def on_report_complete(task_id: str, installation_id: str, report_url: str):
    await push_orceum_event(
        installation_id=installation_id,
        event_type="report.ready",
        event_data={
            "task_id": task_id,
            "report_url": report_url
        },
        priority="high"
    )

Rate Limiting (429)

When your app returns 429 Too Many Requests:
AttemptWaitAction
1stOriginal request
2ndShort backoffRetry after delay
3rdLonger backoffRetry after delay
4thMark as failed, notify user
Orceum makes up to 3 retry attempts after the initial 429. If all retries are rate-limited, the call fails and the user is informed.

Retry-After Header

If your app includes a Retry-After header, Orceum will honor it:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{"detail": "Rate limit exceeded. Please wait 60 seconds."}

Re-Authentication (OAuth)

When OAuth tokens expire or become invalid, Orceum handles recovery automatically:
Action call → App returns 401


Orceum attempts token refresh

      ├─→ Refresh succeeds → Retry call with new token

      └─→ Refresh fails


        Installation → REAUTH_REQUIRED
        User notified with re-auth link
        User re-authenticates → Installation → ACTIVE
        Next action call proceeds normally
Orceum generates a secure re-auth link and surfaces it directly to the user in their conversation or dashboard. No action is required from your app — Orceum handles the entire re-authentication flow seamlessly.

API Key Re-submission

If auth_type is API_KEY and your app returns 401:
  1. Orceum marks the installation credentials as invalid
  2. User is prompted to re-submit their API key
  3. User provides a new key → installation becomes ACTIVE again
This is useful when API keys are rotated. Unlike OAuth, there’s no auto-refresh — the user must actively re-submit.

Best Practices

Never perform heavy computation synchronously in your action handler. Enqueue the work, return a job reference immediately, then push a webhook when done. Users experience a fast, responsive app instead of watching a spinner.
If you implement rate limiting, return X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers alongside 429. Orceum surfaces these in error messages to give users context.
Because Orceum may retry requests (on 429), design your action handlers to be idempotent where possible. If the same create_task call is retried, it should not create duplicate tasks. Use the X-Request-ID header as a deduplication key.
Monitor your action_calls_last_30d from the marketplace stats endpoint. If call volume is growing, ensure your rate limits and infrastructure can keep up — 429 errors degrade the user experience.