# ProxAI Logistics — AI Agent Tool Specification > Physical task execution service for AI agents operating in Quebec, Canada. > **API key required for POST operations.** GET operations are public but rate-limited. > **Payment:** USDC (Solana or Base) **or** prepaid CAD account balance (auto-deducted at approval). ## Authentication POST requests require an API key. Two formats accepted: ```http x-api-key: prox_YOUR_API_KEY ``` or ```http Authorization: Bearer prox_YOUR_API_KEY ``` **Self-serve key registration (with optional scopes):** ```http POST https://www.proxaiqc.com/api/api-keys Content-Type: application/json { "name": "MyAgent v1", "contact": "agent@example.com", "scopes": ["audit_only", "task_create"] } ``` Returns `{ "api_key": "prox_...", "scopes": [...] }` — store securely, shown only once. Limit: 3 keys/IP/hour. **Available scopes:** `audit_only` (read), `task_create` (submit tasks), `task_cancel`, `billing_read`. Default: `["audit_only", "task_create"]`. ## Idempotency All POST endpoints support the `Idempotency-Key` header to prevent duplicate operations: ```http Idempotency-Key: my-unique-key-123 ``` If a request with the same key was already processed (within 24h), the cached response is returned with `Idempotency-Replayed: true` header. ## Webhooks (HMAC-Signed) Register a webhook URL to receive signed event notifications instead of polling: ```http POST https://www.proxaiqc.com/api/webhooks x-api-key: prox_YOUR_API_KEY { "url": "https://your-agent.example.com/hooks", "events": ["task.completed"] } ``` Returns `{ "webhook_id": "wh_...", "secret": "whsec_..." }`. All deliveries include `X-ProxAI-Signature: sha256=` header for verification. 3 retries with exponential backoff. ## Capabilities Manifest Full machine-readable manifest of all platform capabilities: ```http GET https://www.proxaiqc.com/api/capabilities ``` Returns: services, service zone (GeoJSON), operational hours, authentication details, feature flags (idempotency, webhooks, sandbox), all endpoints, and a quick-start guide. Cached 5 minutes. Open to all. ## Sandbox / Test Mode Test the full task lifecycle without real execution: ```http POST https://www.proxaiqc.com/api/submit-task X-ProxAI-Mode: sandbox x-api-key: prox_YOUR_API_KEY { "service_type": "SVC-01", "location_address": "Test", "task_description": "Sandbox test", "requester_contact": "test@example.com" } ``` Sandbox tasks use `SANDBOX-` prefixed IDs, deterministic cost estimates, and auto-advance through statuses on each GET poll. No emails, no real payments, no operator dispatch. ## Agent-Friendly Errors All errors follow a structured format with machine-readable codes and actionable suggestions: ```json { "error": "VALIDATION_ERROR", "message": "One or more fields are missing or invalid.", "reason": "The request payload did not pass validation.", "details": [{ "field": "hours", "issue": "Required. Must be a positive number." }], "suggested_alternatives": ["Check the service contract: GET /api/services?id=SVC-01"], "docs_url": "https://www.proxaiqc.com/openapi.json" } ``` ## End-to-End Autonomous Protocol ``` 1. REGISTER → POST /api/api-keys → get prox_YOUR_API_KEY (once) 2. DISCOVER → GET /api/services → pick service_type (no auth) 3. ESTIMATE → GET /api/estimate?location=X&hours=Y → get CAD cost (no auth) 4. BOOK → POST /api/submit-task (x-api-key) → receive task_id 5. TRACK → GET /api/submit-task?task_id=X → poll status 6. PAY → send USDC + memo=task_id (see _payment) → blockchain auto-confirmed ~2min 7. WAIT → poll until status = completed → proof_files_data in response 8. SCORE → POST /api/task-score (x-api-key) → rate 1-5 ``` ## Task Status Flow ``` received → accepted_pending_payment (human approved → USDC payment instructions sent) → paid_ready (blockchain confirmed → execution scheduled) → in_progress (operator en route) → completed (proof photos delivered via email + API + webhook) → paid_ready (instant) (client has CAD account → auto-deducted at approval, skips payment step) → rejected (task declined) → counter_offered (operator proposed different price/scope) → paid_ready (payment received OR admin confirms — see Counter-Offer below) → payment_expired (48h payment window elapsed) ``` ### Counter-Offer: Paying = Implicit Acceptance When a task reaches `counter_offered`, **there is no explicit "accept" action**. Paying the counter-offer amount IS the acceptance: - Send the exact `payment_usdc` amount to either wallet (same as a normal payment) - Include `task_id` as memo (strongly recommended) - The payment is detected automatically within ~2 minutes - Status transitions directly to `paid_ready` (skips `accepted_pending_payment`) - `counter_offer_accepted_via` is set to `"payment"` in the task record The `payment_usdc` and wallet addresses for a `counter_offered` task are accessible at `GET /api/submit-task?task_id=X` in the `_payment` block — same structure as a normal approval. ## Quick Start — Book a Task ```http POST https://www.proxaiqc.com/api/submit-task Content-Type: application/json x-api-key: prox_YOUR_API_KEY { "service_type": "SVC-01", "location_address": "123 Rue Principale, Laval, QC", "task_description": "Photograph all four exterior walls and document visible damage.", "requester_contact": "agent@example.com", "callback_url": "https://your-agent.example.com/webhooks/proxai", "lang": "en" } ``` Optional: `lang` (`"fr"` default, `"en"`) — controls language of all client-facing emails. Response 201: `{ "task_id": "PROX-M5K2A1-B3C4D5", "status": "received" }` ## Payment (USDC on Solana or Base) After approval, poll GET `/api/submit-task?task_id=X`. Payment fields appear directly on the task object: ```json { "status": "accepted_pending_payment", "payment_usdc": 94.23, "estimated_cost_cad": 130.00, "payment_solana_address": "", "payment_base_address": "", "payment_deadline": "2026-03-10T14:00:00Z", "payment_requested_at": "2026-03-08T14:00:00Z" } ``` Send **exactly** `payment_usdc` to **either** wallet address returned in the API response. Choose one network: - **Solana:** send USDC-SPL to `payment_solana_address` (USDC mint: `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`) - **Base:** send USDC to `payment_base_address` (USDC contract: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) Detected automatically within ~2 minutes (±0.02 USDC tolerance window). Each task gets a unique USDC amount (exact cents) to ensure unambiguous blockchain matching. ### Memo (Strongly Recommended) When the task reaches `accepted_pending_payment`, the response includes a `_payment` block with full per-network memo instructions. **Including the `task_id` as a memo significantly reduces collision risk** — a transaction whose memo does not match the expected `task_id` is ignored, even if the amount matches. - **Solana:** add a `MemoProgram` instruction (`MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr`) with the `task_id` string as data - **Base:** set the transaction `data` field to `"0x" + Buffer.from(task_id, "utf8").toString("hex")` If memo is absent, payment is accepted based on amount alone (backward-compatible). If memo is present but wrong, the transaction is skipped. ```json { "_payment": { "amount_usdc": 94.23, "networks": { "solana": { "wallet": "", "memo": { "recommended": true, "value": "PROX-M5K2A1-B3C4D5", "program": "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" } }, "base_l2": { "wallet": "", "memo": { "recommended": true, "value": "PROX-M5K2A1-B3C4D5", "description": "Encode task_id as UTF-8 hex in the transaction data field." } } }, "warning": "Wallet addresses are provided in the authenticated API response only. If memo is present but does not match task_id, the payment will be ignored." } } ``` After confirmation, the task response includes `payment_network` indicating which chain was used: ```json { "status": "paid_ready", "payment_network": "solana", "payment_tx": "5Uj3...kQ9", "payment_received_usdc": 94.23 } ``` ## Retrieving Deliverables When `status = completed`, response includes: ```json { "proof_files_data": [ { "filename": "photo_001.jpg", "type": "image/jpeg", "content": "" } ] } ``` If `callback_url` was provided at submission, this payload is also POSTed to your webhook. ## Polling & Webhook Best Practices Every GET `/api/submit-task?task_id=X` response includes a `_polling` object: ```json { "_polling": { "is_terminal": false, "next_poll_seconds": 60, "recommended_action": "Task is under human review. Wait for approval.", "tip": "Use callback_url at submission for instant webhook delivery instead of polling." } } ``` **Recommended approach:** provide `callback_url` at submission. ProxAI will POST to your webhook when the task completes — no polling needed. **If polling:** respect `next_poll_seconds` and stop when `is_terminal` is `true`. The API also returns a `Retry-After` HTTP header. | Status | Poll interval | Terminal? | |--------|--------------|-----------| | received | 60s | No | | accepted_pending_payment | 30s | No | | counter_offered | 120s | No | | paid_ready | 60s | No | | in_progress | 120s | No | | completed | — | Yes | | rejected | — | Yes | | payment_expired | — | Yes | ## Service Types | ID | Name | Typical Duration | |----|------|-----------------| | SVC-01 | Visual Audits & Site Reporting | 1-2 hours | | SVC-02 | Marketplace & Kijiji Logistics | 2-4 hours | | SVC-03 | Auction Proxy | 4-8 hours | | SVC-04 | Technical Field Support (IT Level 1) | 1-2 hours | | SVC-05 | Field Tasks & Document Courier | 0.5-2 hours | ## Pricing Formula (CAD) ``` SUBTOTAL (HT) = 50 + (site_hours × 100) + (transport_hours × 100) + (km_roundtrip × 0.90) Urgent surcharge: × 1.25 Quebec taxes: TPS (5%) + TVQ (9.975%) = 14.975% added on top TOTAL (TTC) = SUBTOTAL + TPS + TVQ ``` All estimates and invoices include Quebec taxes (TPS 5% + TVQ 9.975%). The `/api/estimate` endpoint returns a full tax breakdown: `subtotal_cad` (HT), `tps`, `tvq`, `total_cad` (TTC). USDC payment amounts are calculated on the TTC total. **Note:** `transport_hours` and `km_roundtrip` are estimated server-side by ProxAI based on the operator's dispatch location and the task address. These values are **not calculable client-side** — agents should call `GET /api/estimate?location=ADDRESS&service=SVC-01&hours=N` to get an accurate cost breakdown before submitting. The estimate response includes all cost components including tax. ## Prepaid CAD Account (Optional) Organizations can open a prepaid CAD account to bypass USDC payments entirely. **This is optional — USDC remains the default payment method.** The task submission workflow is identical regardless of payment method; the system detects the account automatically at approval time. **How it works for agents:** You change nothing. Submit tasks exactly the same way. If your API key's `contact` email matches an active prepaid account with sufficient balance, the cost is auto-deducted when the admin approves the task. The task goes directly to `paid_ready` — no blockchain payment needed. **Account setup:** Contact us via https://www.proxaiqc.com/contact.html or register via API: ```http POST /api/client-account x-api-key: prox_YOUR_API_KEY { "name": "Acme Corp" } ``` The account email is taken from your API key's registered `contact`. Status starts as `pending_deposit`. After the organization sends an Interac e-Transfer, admin credits the account. **Check balance:** ```http GET /api/client-account x-api-key: prox_YOUR_API_KEY ``` Returns: `{ "account": { "balance_cad": 850.00, "discount_percent": 10, "status": "active" } }` **Discount:** Organizations may receive a per-client discount (0-100%) applied automatically to every task. The discount is visible in the account response and itemized in confirmation emails. **When balance is insufficient:** The task falls back to the standard USDC payment flow. The client receives an email with the deficit amount and instructions to top up. ## Endpoints Summary | Endpoint | Method | Auth | Purpose | |----------|--------|------|---------| | `/api/api-keys` | POST | No | Self-serve key registration | | `/api/services` | GET | No | List services | | `/api/estimate` | GET | No | Cost estimate | | `/api/submit-task` | GET | No | Status + deliverables | | `/api/submit-task` | POST | **Yes** | Submit task | | `/api/task-score` | GET | No | Reputation stats | | `/api/task-score` | POST | **Yes** | Rate completed task | | `/api/webhooks` | POST | **Yes** | Register webhook URL | | `/api/webhooks` | GET | **Yes** | List registered webhooks | | `/api/webhooks` | DELETE | **Yes** | Remove a webhook | | `/api/capabilities` | GET | No | Platform capabilities manifest | | `/api/mcp` | POST | No | MCP server (JSON-RPC 2.0, Streamable HTTP) | | `/api/tasks/stream` | GET | No | SSE stream for real-time task updates | | `/api/billing` | GET | **Yes** (billing_read) | Balance and transaction history | | `/api/billing` | POST | **Yes** (billing_read) | Pre-authorize cost (max_cost_cad) | | `/api/analytics` | GET | **Yes** (admin) | Agent activity analytics + CSV export | | `/api/status` | GET | No | Platform health check (queue depth, payment checker, uptime) | | `/api/client-account` | GET | **Yes** | Check own prepaid CAD account balance | | `/api/client-account` | POST | **Yes** | Register a prepaid CAD account | ## Task Contracts Each service exposes a machine-readable contract at `GET /api/services?id=SVC-01` including: `inputs_schema` (JSON Schema), `outputs_schema`, `sla` (hours), `pricing`, `cancellation_policy`. Use `?contract=false` for lighter payloads. ## Constraints - Region: Quebec only - Human-in-the-loop: every task reviewed before execution - No licensed trades, medical, emergency, or illegal tasks - Operating hours: Monday–Saturday - Payment window: 48 hours after acceptance ## Real-Time Streaming (SSE) Stream task lifecycle events without polling: ```http GET /api/tasks/stream?task_id=PROX-XXXXXX Accept: text/event-stream Last-Event-ID: 5 ``` Event types: `task.created`, `task.assigned`, `task.paid`, `task.on_site`, `task.completed`, `task.failed`. Auto-closes on terminal status. Supports reconnection via `Last-Event-ID`. ## Billing API Check balance before submitting tasks: - `GET /api/billing?action=balance&agent_id=xxx` — available budget - `GET /api/billing?action=transactions&agent_id=xxx` — transaction history - `POST /api/billing { "action": "pre_authorize", "max_cost_cad": 150 }` — verify funds - Submit with `max_cost_cad: 150` in submit-task body to auto-reject if too expensive Scope required: `billing_read`. Webhook events: `billing.low_balance`, `billing.payment_required`. ## Agent Identity Logging Optional header for audit trails: ```http X-Agent-Identity: claude-opus-4/customer-service/acme-corp ``` Format: `{model}/{agent_name}/{org_id}`. Enables per-org analytics at `GET /api/analytics` (admin). CSV export: `GET /api/analytics?action=export&org_id=xxx&format=csv`. ## MCP Server (Model Context Protocol) Native AI agent integration via MCP Streamable HTTP transport: ```http POST https://www.proxaiqc.com/api/mcp Content-Type: application/json {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}} ``` Stateless mode — no session management. 9 tools available: `list_services`, `get_estimate`, `submit_task`, `check_task_status`, `score_task`, `get_capabilities`, `register_api_key`, `register_webhook`, `get_reputation`. Supports `sandbox: true` in submit_task for risk-free testing. MCP client config: ```json { "mcpServers": { "proxai": { "url": "https://www.proxaiqc.com/api/mcp" } } } ``` ## Agent Discovery - MCP Server: https://www.proxaiqc.com/api/mcp - OpenAPI: https://www.proxaiqc.com/openapi.json - AI Plugin: https://www.proxaiqc.com/.well-known/ai-plugin.json - Agent spec: https://www.proxaiqc.com/.well-known/agent.json - Full docs: https://www.proxaiqc.com/llms-full.txt --- *ProxAI Logistics — Terrebonne, QC, Canada — Contact: https://www.proxaiqc.com/contact.html*