OfficeX Platform
OfficeX is a membership-based app store. Users buy credits ($0.03 each: $0.02 profit + $0.01 ecosystem liability). Apps charge credits via reserve/settle. Vendors earn credits and payout to fiat (USDC on Solana or bank transfer, $0.01/credit).
Get your credentials at: https://officex.app/store/en/developer/
Environments
| Env | API Base | Chat Stream |
|---|
| Staging (default) | INLINECODE0 | INLINECODE1 |
| Production |
https://cloud.officex.app/v1 |
https://chat.cloud.officex.app/ |
Authentication
| Mode | Headers | Scope |
|---|
| None | — | Public catalog, vouchers, auth endpoints |
| Master Key |
x-officex-user-id +
x-officex-master-key | Profile, installs, wallets, vendor apps |
| Install Secret |
x-officex-install-id +
x-officex-install-secret | Billing: reserve, settle, cancel, inbox |
| Install Secret (alt) |
x-officex-user-id +
x-officex-app-id +
x-officex-install-secret | Same as above (alternative lookup) |
| Superadmin |
x-officex-admin-secret | Full system (
/admin/*) |
Install Secret is billing only — your app manages its own user authentication separately. The install secret handles the money, your app handles everything else.
Credit Economy
CODEBLOCK0
Decimal Credits
Credits support decimals. Rounding up to 1 credit ($0.03) is expensive for small operations:
| Operation | Credits | User Pays |
|---|
| Micro task | 0.1 | $0.003 |
| Small task |
0.25 | $0.0075 |
| Medium task | 0.5 | $0.015 |
| Standard | 1.0 | $0.03 |
Best practice: Price based on actual cost. If an API call costs $0.001, charge ~0.07 credits (2x markup).
Dual Roles
A single OfficeX account can be both Consumer (install and use apps) and Vendor (create apps and earn credits).
API Endpoints
Auth (No Auth)
CODEBLOCK1
Testing mode: OTP hardcoded to 0000, email sending disabled.
User Profile [Master Key]
CODEBLOCK2
Installations [Master Key]
CODEBLOCK3
INLINECODE14 : unix timestamp (-1 = never, default = now + 30d). lifetime_spend_limit: -1 = unlimited.
App-scoped routes (Install Secret auth):
CODEBLOCK4
Vendor Apps [Master Key]
CODEBLOCK5
Public Catalog (No Auth)
CODEBLOCK6
Credits & Balance [Master Key]
CODEBLOCK7
Reserve & Settle [Install Secret]
CODEBLOCK8
INLINECODE16 = complete + refund remainder. final: false (default) = sip (partial).
Reserve errors: INSTALL_EXPIRED, RATE_LIMITED, INSUFFICIENT_FUNDS, DUPLICATE_JOB, INLINECODE22
Wallets [Master Key]
CODEBLOCK9
Payouts [Master Key]
CODEBLOCK10
Payout state machine: pending → burned → completed | failed (failed = credits restored). Frequency: end of every month. Rate: $0.01 per credit.
Vouchers
CODEBLOCK11
Chat [Master Key]
CODEBLOCK12
Streaming (Function URL, NOT API Gateway):
CODEBLOCK13
Stream protocol lines (emitted before SSE data):
- -
t:{threadId}\n — resolved thread ID (always emitted) - INLINECODE25 — tracer ID (emitted when
tracer_id present in request) - INLINECODE27 — status updates
Inbox, Prompts, Refs, Uploads [Master Key]
CODEBLOCK14
Admin [Superadmin]
All under /admin/* with x-officex-admin-secret:
Users: GET /admin/users, GET/PATCH /admin/users/{id}, GET /admin/users/{id}/wallets
Apps: GET /admin/apps, GET/PATCH/DELETE /admin/apps/{id}
Wallets: GET /admin/wallets, GET /admin/wallets/{id}, POST /admin/wallets/{id}/adjust { amount }
Treasury: GET /admin/treasury, POST /admin/reconcile, GET /admin/audit
Payouts: GET /admin/payouts, GET /admin/payouts/{id}, POST /admin/payouts/{id}/approve, POST /admin/payouts/{id}/reject
Vouchers: POST /admin/vouchers, GET /admin/vouchers, INLINECODE47
Error Format
CODEBLOCK15
| Code | HTTP | Description |
|---|
| INLINECODE48 | 401 | Missing or invalid auth headers |
| INLINECODE49 |
401 | Secret doesn't match hash |
|
INVALID_REQUEST | 400 | Malformed request body |
|
APP_NOT_FOUND | 404 | App doesn't exist |
|
USER_NOT_FOUND | 404 | User doesn't exist |
|
WALLET_NOT_FOUND | 404 | Wallet doesn't exist |
|
RESERVATION_NOT_FOUND | 404 | Reservation doesn't exist |
|
INSTALL_NOT_FOUND | 404 | Installation doesn't exist |
|
INSTALL_EXPIRED | 403 | Billing authorization expired |
|
RATE_LIMITED | 429 | Exceeded rate limit |
|
INSUFFICIENT_FUNDS | 402 | Wallet balance too low |
|
LIFETIME_LIMIT_REACHED | 403 | Cumulative spending exceeds lifetime limit |
|
FORBIDDEN | 403 | Accessing another user's resources |
|
DUPLICATE_REQUEST | 409 | Idempotency key collision |
|
DUPLICATE_JOB | 409 | Job ID already has reservation |
|
PREVIOUS_FAILURE | 409 | Idempotency collision (failed, use new key) |
|
PAYMENT_FAILED | 402 | External payment rejected |
|
PAYOUT_FAILED | 500 | Fiat transfer failed |
|
INTERNAL_ERROR | 500 | Unexpected server error |
Using 3rd Party Apps
Whenever you use an app on OfficeX, you can grab the agent_context from the app installation. This may give you app secrets to interact with their REST API. However, not all apps might have it. Every app has their own skill.md that you can copy online or request via OfficeX API.
App Lifecycle (Developer Guide)
1. Create Your App
Endpoint: POST /register-app [Master Key]
CODEBLOCK16
Example:
CODEBLOCK17
Each app gets a discrete wallet (destination_wallet_id). Earnings go there, not your personal wallet. documentation is injected into the AI chat agent's system prompt. context_prompt provides additional instructions for the AI agent.
2. Update Your App
Endpoint: PATCH /users/me/apps/{app_id} [Master Key] — All fields optional, set to null to clear:
CODEBLOCK18
3. List App's Installs (Vendor View)
Endpoint: GET /users/me/apps/{app_id}/installs [Master Key]
CODEBLOCK19
Installation Flow (When Users Install Your App)
When a user installs your app, OfficeX:
- 1. Creates an Installation Record linking user to app
- Generates an Install ID and Install Secret (scoped billing credentials)
- Sets rate limits (user-specified or your suggested defaults)
- Sets allowed_until expiry (default: 30 days, or
-1 for no expiry) - Fires an INSTALL webhook to your
webhook_url (if configured)
The install endpoint accepts both app_id (UUID) and slug (string) in the path parameter.
Webhook Events
Your app receives lifecycle events at webhook_url. Envelope: { event, payload, uuid }.
INSTALL Event:
CODEBLOCK20
UNINSTALL Event: payload: INLINECODE80
RATELIMITCHANGE Event: payload: INLINECODE81
Webhook Response: Your response for INSTALL can include agent_context (only this key is extracted). Values are stored on the installation and injected into the user's AI agent prompt:
CODEBLOCK21
Delivery: POST, application/json, 25s timeout, fire-and-forget (no retries in v1).
Note: Not all apps need a webhook. Apps where the user supplies their own credentials (e.g., Telegram bot token) can skip the webhook entirely and use PATCH /installs/{install_id}/context from within the app UI post-install. See Agent Context for details.
Credit Billing System
The Reserve → Sip → Settle Pattern
CODEBLOCK22
Reserve (Lock Funds)
INLINECODE86 [Install Secret]
CODEBLOCK23
CODEBLOCK24
Internally: user's wallet.available decreases, wallet.reserved increases, creates RESV#<job_id>.
| Error Code | Meaning |
|---|
| INLINECODE90 | INLINECODE91 timestamp has passed |
| INLINECODE92 |
Cumulative spending exceeds limit |
|
RATE_LIMITED | Hourly/daily/monthly limit exceeded |
|
INSUFFICIENT_FUNDS | Not enough available credits |
|
DUPLICATE_JOB | This job_id already has a reservation |
Sip (Progressive Settlement)
INLINECODE96 (or POST /settle) [Install Secret]
CODEBLOCK25
Example — enriching 100 leads:
CODEBLOCK26
Settle (Final)
CODEBLOCK27
Remaining reserved funds (if any) are refunded to user. Credits move to your app's wallet.
Cancel (Full Refund)
INLINECODE98 [Install Secret]
CODEBLOCK28
Rate Limits & Allowances
Rate limits are per (user, app) pair — each installation has independent limits.
| Window | Default | Description |
|---|
| Hourly | 100 reservations | Resets each hour |
| Daily |
300 reservations | Resets each day |
| Monthly | 1000 reservations | Resets each month |
Minimum rate limits (developer-set floor): Users cannot go below these values.
allowed_until: Unix timestamp (-1 = never expires, default = now + 30 days). When expired, all /reserve calls fail with INSTALL_EXPIRED. Enables pseudo-subscription billing.
lifetime_spend_limit: Total credits an app can ever charge across all time. Set to -1 for unlimited. Fails with LIFETIME_LIMIT_REACHED when exceeded.
| App Type | Suggested Hourly | Daily | Monthly |
|---|
| Lead enrichment | 50 | 200 | 2000 |
| Data export |
10 | 50 | 200 |
| AI generation | 20 | 100 | 1000 |
| Real-time lookup | 100 | 500 | 5000 |
Agent Context (AI Chat Integration)
When users chat with OfficeX AI, the agent receives your app's documentation and context_prompt. Store per-install credentials via:
INLINECODE107 [Master Key] or PATCH /installs/{install_id}/context [Install Secret]
CODEBLOCK29
Validation: Max 50 keys, 200 chars/key, 1000 chars/value.
Two patterns for setting agent_context:
- 1. Webhook-response (auto): Return credentials in your INSTALL webhook response → auto-applied as
agent_context. Best for apps that provision credentials server-side on install.
- 2. Post-install from app UI (manual): App collects credentials from the user inside its own iframe/UI after install, then PATCHes them via install secret auth. Best for apps where the user supplies their own API key/token (e.g., Telegram bot token, OpenAI key, Stripe key). Flow:
- User installs app (no extra params needed)
- User opens app → enters their credentials in the app's UI
- App calls
PATCH /installs/{install_id}/context with install secret auth
- Credentials are stored on the installation → available to AI agent via INLINECODE112
CODEBLOCK30
Sending Inbox Messages
Notify users about job status, results, or important updates:
INLINECODE113 [Install Secret]
CODEBLOCK31
CODEBLOCK32
Billing Patterns
Pattern 1: Free Apps
No reservations needed. Use inbox messages to communicate.
Pattern 2: One-Time Purchase
Reserve and settle immediately for discrete actions:
CODEBLOCK33
Pattern 3: Usage-Based (Progressive Sip)
For long-running jobs, bill incrementally:
CODEBLOCK34
Pattern 4: Subscription-like
Use allowed_until for time-based access:
CODEBLOCK35
Pattern 5: Internal Credits System (Recommended)
Decouple your app from OfficeX API by maintaining your own internal ledger:
- 1. Reserve + settle OfficeX credits in bulk
- Mint equivalent internal credits in your DB
- Your app logic consumes internal credits only — no OfficeX API calls during normal operation
CODEBLOCK36
CODEBLOCK37
Benefits: decoupled from API availability, flexible internal pricing, auditability, batch funding, simpler error handling.
Frontend Integration (Iframe Embedding)
When users launch your app from OfficeX, it loads in an iframe with credentials as URL params:
CODEBLOCK38
Extracting Credentials
JavaScript/TypeScript:
CODEBLOCK39
Python (Flask):
CODEBLOCK40
Required: Allow OfficeX to Embed Your App
Your app must allow the OfficeX domain to embed it via iframe:
CODEBLOCK41
Next.js (next.config.js):
CODEBLOCK42
Express.js:
CODEBLOCK43
Without this header: blank screen or console errors about "refused to frame."
Security:
- - Never expose
install_secret to users (use sessionStorage, not localStorage) - Validate on backend for sensitive operations
- HTTPS required
- Handle missing params gracefully (users may bookmark deep links)
Webhook Authentication Flow (SSO)
The INSTALL webhook enables seamless single sign-on:
CODEBLOCK44
Implementing onInstall Authentication
Step 1: Handle webhook:
CODEBLOCK45
Step 2: Look up user when iframe loads:
CODEBLOCK46
Handling Webhook Failures
Webhooks are fire-and-forget (no retries). Always have a fallback:
CODEBLOCK47
Fault Tolerance
Your app should treat OfficeX as an external payment layer, not a core dependency.
Principles:
- 1. Wrap all OfficeX API calls in try/catch with timeouts (3-5 seconds)
- Your app should function if all OfficeX code was removed — OfficeX is how you get paid, not your runtime
- Use the Internal Credits pattern (Pattern 5) for maximum resilience
Resilient billing wrapper:
CODEBLOCK48
Error handling for reservations:
CODEBLOCK49
Practical guidelines:
- - Set aggressive timeouts (3-5 seconds) on all OfficeX API calls
- If reserve fails, consider letting user proceed and retrying billing later
- Webhooks are fire-and-forget — always have a fallback path (create users on-the-fly from iframe params)
- Consider a simple toggle to disable OfficeX billing during development/testing
- Log OfficeX errors instead of throwing unhandled exceptions
Complete Integration Example
1. Register app:
CODEBLOCK50
2. Handle webhook:
CODEBLOCK51
3. Handle iframe entry:
CODEBLOCK52
4. Bill from your app:
CODEBLOCK53
Quick Start Workflows
Consumer — Register + Fund + Install:
CODEBLOCK54
Developer — Register App + Billing:
CODEBLOCK55
Vendor Payout:
CODEBLOCK56
Tracers (Cross-Thread Correlation)
A tracer_id is a string (format: trc_{timestamp36}-{random}) that links causally-related threads and schedule runs. Use cases: schedule runs weekly → each run creates a thread → all threads share one tracer_id → frontend can render a unified timeline.
Where tracer_id appears:
- - Threads:
POST /users/me/chats body accepts tracer_id. GET /users/me/chats?tracer_id=trc_xxx filters by tracer. PATCH can set/clear it (null to remove). - Schedules:
POST /users/me/schedules body accepts tracer_id (auto-generated as trc_* if omitted). All schedule responses include it. - Schedule Runs: Each run record includes
tracer_id copied from the schedule. - Chat Stream: Body accepts
tracer_id. Stream protocol emits tracer:{tracerId}\n after t:{threadId}\n.
Example flow:
- 1. Create schedule →
tracer_id: "trc_abc123" auto-generated - Schedule runs → creates thread with INLINECODE133
- Query
GET /users/me/chats?tracer_id=trc_abc123 → returns all threads from this schedule
FAQ
How do I test without real money? Use vouchers via admin panel or test voucher codes.
Can my app have multiple pricing tiers? Yes. Your app logic decides how many credits to reserve per action.
What happens if my webhook is down? Webhooks are fire-and-forget. Handle gracefully by polling installation status or creating users on-the-fly from iframe params.
Can I transfer credits between apps I own? No. Credits only flow through reservation/settlement. Each app wallet is independent.
How do I handle long-running jobs that fail? Reserve upfront, sip as work completes, cancel on failure (refunds all unsettled credits), send inbox message explaining what happened.
How does the AI chat agent interact with my app? The agent receives your documentation and context_prompt. If agent_context has credentials, the agent calls your API via http_request tool. Make sure docs include clear API instructions.
OfficeX 平台
OfficeX 是一个基于会员制的应用商店。用户购买积分(每个$0.03:$0.02利润 + $0.01生态系统负债)。应用通过预留/结算来收取积分。供应商赚取积分并兑换为法定货币(Solana上的USDC或银行转账,$0.01/积分)。
获取凭证: https://officex.app/store/en/developer/
环境
| 环境 | API 基础地址 | 聊天流 |
|---|
| 预发布(默认) | https://staging-backend.cloud.officex.app/v1 | https://chat-staging.cloud.officex.app/ |
| 生产环境 |
https://cloud.officex.app/v1 | https://chat.cloud.officex.app/ |
认证
| 模式 | 请求头 | 范围 |
|---|
| 无认证 | — | 公开目录、凭证、认证端点 |
| 主密钥 |
x-officex-user-id + x-officex-master-key | 个人资料、安装、钱包、供应商应用 |
| 安装密钥 | x-officex-install-id + x-officex-install-secret | 计费:预留、结算、取消、收件箱 |
| 安装密钥(备选) | x-officex-user-id + x-officex-app-id + x-officex-install-secret | 同上(备选查询方式) |
| 超级管理员 | x-officex-admin-secret | 完整系统(/admin/*) |
安装密钥仅用于计费——您的应用自行管理用户认证。安装密钥处理资金,您的应用处理其他所有事务。
积分经济
用户购买积分 → 国库负债增加(零和:国库 + 所有钱包 = 0)
应用预留积分 → 从用户钱包锁定
应用逐步/结算 → 积分转移到应用钱包
供应商提现 → 积分兑换为法定货币,国库负债减少
小数积分
积分支持小数。对于小额操作,向上取整到1积分($0.03)成本较高:
0.25 | $0.0075 |
| 中等任务 | 0.5 | $0.015 |
| 标准任务 | 1.0 | $0.03 |
最佳实践: 根据实际成本定价。如果API调用成本为$0.001,收取约0.07积分(2倍加价)。
双重角色
单个OfficeX账户可以同时是消费者(安装和使用应用)和供应商(创建应用并赚取积分)。
API 端点
认证(无需认证)
POST /auth/register { email } → { success, message }
POST /auth/login { email, password? } → { success, apikey?, userid? }
POST /auth/verify-otp { email, code } → { success, apikey, userid, wallet_id? }
POST /auth/resend { email } → { success, message }
POST /auth/forgot-password { email } → { success, message }
POST /auth/reset-password { email, code, new_password } → { success, message }
POST /auth/set-password { password } [MK] → { success, message }
POST /auth/rotate-key { email } → { success, message }
POST /auth/confirm-rotate-key { email, code } → { success, api_key }
POST /register-user { email } → { userid, walletid, api_key } (旧版)
测试模式: OTP硬编码为0000,禁用邮件发送。
用户资料 [主密钥]
GET /users/me → { user: { userid, email, walletid, status } }
PATCH /users/me { email? } → { user }
POST /users/me/rotate-key { newmasterkey } → { success }
GET /users/me/vouchers → { vouchers[] }
安装 [主密钥]
GET /users/me/installs → { installs[] }
GET /users/me/installs/{id} → { install (含使用统计) }
POST /install/{appidorslug} { maxperhour?, maxperday?, maxpermonth?, alloweduntil? }
→ { appid, installid, installsecret, agentcontext? } ⚠️ 密钥仅显示一次
DELETE /users/me/installs/{id} → { success }
PATCH /users/me/installs/{id} { maxperhour?, maxperday?, maxpermonth?, alloweduntil?, lifetimespend_limit? }
→ { install }
POST /users/me/installs/{id}/rotate-secret → { install_secret }
PATCH /users/me/installs/{id}/context { key: val | null } → { agent_context }
alloweduntil:Unix时间戳(-1 = 永不过期,默认 = 当前时间 + 30天)。lifetimespend_limit:-1 = 无限制。
应用范围路由(安装密钥认证):
PATCH /installs/{installid}/context { key: val | null } → { agentcontext }
POST /installs/{installid}/inbox { id, title, text, url?, icon? } → { messageid }
供应商应用 [主密钥]
GET /users/me/apps → { apps[] }
POST /register-app (见下方完整模式)
→ { appid, destinationwallet_id }
GET /users/me/apps/{app_id} → { app }
PATCH /users/me/apps/{app_id} (见下方完整模式)
→ { app }
DELETE /users/me/apps/{app_id} → { success }
GET /users/me/apps/{app_id}/inbox → { reservations[], pagination? }
POST /users/me/apps/{appid}/inbox/{logid}/ack → { success }
GET /users/me/apps/{app_id}/installs → { installs[] }
公开目录(无需认证)
GET /apps → { apps[], pagination? }
GET /apps/{app_id} → { app }
积分与余额 [主密钥]
POST /purchase-credits { amount, paymentmethod: { type, token }, idempotencykey? }
→ { creditsadded, newbalance, transaction_id }
GET /balance → { wallet_id, available, reserved, total }
预留与结算 [安装密钥]
POST /reserve { amount, job_id, metadata? }
→ { reservationid, amountreserved }
POST /settle { reservation_id, amount, final? }
→ { settledamount, remainingreserved, status }
GET /reservations/{id} → { reservation }
POST /reservations/{id}/cancel → { refunded_amount, status }
POST /reservations/{id}/settle { amount, final? } → { settled_amount, status }
final: true = 完成 + 退还剩余。final: false(默认)= 逐步(部分结算)。
预留错误:INSTALLEXPIRED、RATELIMITED、INSUFFICIENTFUNDS、DUPLICATEJOB、LIFETIMELIMITREACHED
钱包 [主密钥]
GET /wallets/{id} → { walletid, available, reserved, total, ownertype }
GET /wallets/{id}/transactions ?limit=&cursor= → { transactions[], pagination? }
GET /wallets/{id}/transactions/{log_id} → { transaction }
GET /wallets/{id}/reservations ?direction= → { reservations[] }
GET /wallets/{id}/reservations/{resv_id} → { reservation }
GET /wallets/{id}/payouts → { payouts[] }
GET /wallets/{id}/payouts/{payout_id} → { payout }
提现 [主密钥]
POST /payout { walletid, amount, destination: { type, accountid }, idempotency_key? }
→ { payout_id, status }
提现状态机:pending → burned → completed | failed(failed = 积分恢复)。频率:每月末。费率:每积分$0.01。
凭证
GET /vouchers/{code}