ADR 0007: Agent commerce โ public REST + MCP API at api.acesense.io
- Status: โ Accepted
- Date: 2026-04-26
- Deciders: Akshay Sarode
- Tags: api, billing, mcp, agents, infrastructure
Contextโ
In April 2026 the AceSense GPU pipeline was reachable from one place: the Flutter app, via the requestUploadPath callable. Discovery audits flagged that the marketing site advertised an MCP server card with status: "planned" but no actual MCP endpoint, no public REST API, and no agent payment surface.
Three forces pushed for opening this up:
- Adjacent demand. Tennis-coaching bots, training-platform integrations, and club-management software are real buyers of "give me back a per-shot analysis JSON for a video URL." None of them want to ship a Flutter app.
- Marginal cost is well-understood. RunPod GPU cost is ~โฌ0.05โ0.10/min depending on which GPU. Pricing at โฌ0.75/min keeps healthy margin.
- Existing infra reuse. The pipeline already runs from a
videos/{uid}/{sessionId}/...Storage write triggeringprocessVideoOnUpload. An agent submission can reuse the trigger by writing to the same path with a differentuserIdnamespace. No backend rewrite needed.
The blocker was abuse risk: agent-scale submissions multiply the impact of every threat in compliance/upload-threat-model.md. Without the P0/P1 controls in place, opening this up would be reckless.
Options consideredโ
Option A โ REST + MCP, prepaid credits, behind threat-model controlsโ
- Pros: Real new revenue surface; closest fit to how agent operators actually buy compute today; leverages the existing pipeline; abuse risk capped by per-key quota + per-key balance + content-validation gates.
- Cons: Real build (โฅ1 week even reusing pipeline); needs Stripe wiring; legal exposure (DPA scope, content-licensing clarity); Cloud Functions cost grows with traffic.
- Cost: Engineering 1 week + ongoing Stripe % + Cloud Functions invocation cost.
Option B โ MCP-only (no REST)โ
- Pros: Less surface area; targets the LLM-tool integration market specifically.
- Cons: Excludes operators who don't speak MCP yet (most server-to-server integrations); can't run x402 / OpenAPI discovery cleanly without a REST surface.
- Cost: A bit less than A.
Option C โ REST-only (no MCP)โ
- Pros: Simplest spec.
- Cons: Misses the LLM-tool ecosystem (Claude desktop, ChatGPT custom GPTs), which is exactly where agent-discoverability research is concentrated today.
Option D โ Hold, ship laterโ
- Pros: Buys time to land a Stripe deal, finalize DPA, etc.
- Cons: Discovery audits already advertise a "planned" surface; sitting on it indefinitely makes the audit assertions look untrue. Threat-model controls have to ship anyway for the human path.
Decisionโ
We will ship Option A: REST + MCP at api.acesense.io, behind the threat-model P0/P1 controls.
- REST base:
https://api.acesense.io/v1โ/jobs,/usage,/pricing,/healthz. OpenAPI 3.1 published at/openapi.json. - MCP base:
https://api.acesense.io/mcpโ Streamable-HTTP transport, six tools (analyze_tennis_video, get_job_status, get_analysis_result, get_pricing, get_my_usage, list_my_jobs), sevenacesense://*.mdresources. - Auth:
Authorization: Bearer phk_<keyId>_<secret>, SHA-256-hashed at rest, constant-time compare. Keys created via Firebase-auth-callablecreateApiKey({name, plan}). - Pricing: โฌ0.75/min default,
ceil(durationSeconds/60) * 75cents. โฌ10 free credit per new key. - Billing: Prepaid balance in Firestore (
api_keys/{keyId}.balanceCents), credited manually through admin balance adjustment. Payment-rail integration deferred until volume justifies. - Rate limits: Per-key sliding window โ default 10 req/min + 200 jobs/day.
Threat-model controls landed alongside this work (per ADR-0007 prerequisite): atomic per-user quota, magic-byte file validation, 30-min signed-URL TTL, audit log, locked Firestore rules. ffprobe runtime check is documented as deferred โ needs the binary bundled in the deploy.
Consequencesโ
Positiveโ
- New revenue surface decoupled from App Store / Google Play.
- Same pipeline infra serves both consumer (in-app) and agent (API) traffic โ no fork.
- Threat-model P0/P1 controls protect both paths.
- Discovery surface (api-catalog, mcp/server-card, x402, MPP, ACP, UCP) is now real, not aspirational.
Negativeโ
- No self-serve top-up yet. Agent operators can use credited balances, but payment collection is manual until a real payment rail is worth shipping.
- DPA scope grows. When an agent processes a real human's video, AceSense becomes a sub-processor. New DPA template needed.
- CSAM / illegal-content risk increases at agent scale. Magic-byte gate is in; first-frame moderation is on the P1 list and not yet wired. Until it lands, content moderation depends on the magic-byte gate + RunPod's own filters + a human review queue.
- One more payment vendor when wired. Adds processing fees and cross-border data-processing considerations.
Neutralโ
- Per-minute pricing is industry-standard for GPU-tied work; easy to compare against alternatives.
- API key model mirrors how every other agent platform issues credentials; little surprise for operators.
Follow-up actionsโ
Doneโ
- Implement
apiServerREST + JSON-RPCmcpServerCloud Functions. - Per-user upload quota + magic-byte + signed-URL audit + locked Firestore rules (threat-model P0/P1).
- Update
/.well-known/mcp/server-card.jsonfromstatus: "planned"โstatus: "live". - Publish
/.well-known/x402,/.well-known/mpp.json, ACP/UCP transactional discovery. - Marketing surface at
/agentswith full pricing + discovery table. - Custom domain
api.acesense.ioโ separate hosting siteacesense-prod-apiwith/v1/**โapiServerand/mcpโmcpServerrewrites. Repo:acesense-api-hosting/. DNS configured 2026-04-26. - ffprobe runtime metadata gate โ
@ffprobe-installer/ffprobe+fluent-ffmpegbundled in the function image;ffprobeGate()inshared/video-validation.tscross-checks claimed duration/width/height within ยฑ5% tolerance, fails open when binary unavailable so partial deploys don't wedge. - First-frame Cloud Vision moderation โ
moderateFirstFrame()inshared/moderation.tsextracts a still at 5 s, ships to Cloud Vision SafeSearch, rejects on adult/violence/racy โฅ LIKELY. Audit row per decision inmoderation_audit/{autoid}. Currently gated off byGOOGLE_CLOUD_VISION_ENABLEDenv var until Vision API billing is enabled โ see pending item below. - Admin panel UI โ
/developerroute inacesense-adminexposes Create / List / Revoke for API keys, with the one-shot full-key reveal.
Pending โ manual external setupโ
- Payment rail. Pick the provider and ship checkout/webhook only when there is real paid demand. Until then, use
adminAdjustApiKeyBalancefor credited agent balances. - Enable Google Cloud Vision API on
acesense-prod+ setGOOGLE_CLOUD_VISION_ENABLED=trueenv var onprocessVideoOnUpload. The code path is wired and tested (6 unit tests); it just no-ops until the env var flips. Surface impact: the magic-byte + ffprobe gates remain in force; the Cloud Vision check is the deferred extra layer for adult/violence/racy first-frame content.
Pending โ internalโ
- DPA template for agent operators โ sub-processor agreement covering when an agent submits a real human's video. Owner: legal review.
- Real machine-payment integration โ discovery is published; actual settlement integration deferred until โฅ1 customer requests it. Spec is still moving.
Referencesโ
- Repo:
acesense-auth-function/api/,acesense-auth-function/mcp/ - Marketing: acesense.io/agents
- Reference doc: reference/agent-api
- Threat model: compliance/upload-threat-model
- Related: ADR-0005 PostHog EU, ADR-0006 Allow all crawlers