REST API
A human-friendly HTTP API for ONCE music distribution: upload assets, run AI detection, generate cover art, submit releases, and monitor delivery — the same capabilities, authentication, billing, and validation as the ONCE MCP server, exposed as conventional REST endpoints for developers who are not using an MCP client.
- Base URL:
https://once.app/v1 - Machine-readable spec:
GET /v1/openapi.json(OpenAPI 3.1) - API index:
GET /v1 - You do not need to know anything about MCP to use this API.
The MCP server (https://beta.once.app/api/mcp) remains fully supported —
this REST API is an additional surface over the same platform, not a
replacement. If you’re building an AI-agent integration, MCP gives you tool
discovery and native auth challenges; if you’re building a backend or app,
use this REST API.
Billing
Billing is identical to the MCP server: 1 credit per human song, 2 credits per AI-detected song. Submissions debit credits from the authenticated account. AI-detected songs bill at 2 credits automatically.
Quick start
BASE=https://once.app/v1
AUTH="Authorization: Bearer $ONCE_ACCESS_TOKEN"
# 0. Read the metadata rules (public; your inputs are validated against these)
curl $BASE/metadata-rules
# 1. Confirm who you are and your credit balance
curl -H "$AUTH" $BASE/me
curl -H "$AUTH" $BASE/me/credits
# 2. Upload cover art (small file, base64) — or generate it, see /cover-art
curl -X POST $BASE/files -H "$AUTH" -H 'Content-Type: application/json' \
-d '{ "type": "coverArt", "file_name": "cover.jpg", "data_base64": "<base64>" }'See Authentication for how to obtain an access token, then Uploads, AI Detection, and Releases for the full workflow.
Endpoint index
Discovery & metadata
| Endpoint | Description |
|---|---|
GET /v1 | API index. |
GET /v1/openapi.json | OpenAPI 3.1 description of this API. |
GET /v1/metadata-rules | Metadata policy hitlist (markdown; Accept: application/json for a JSON wrapper). |
GET /v1/release-schema | Authoritative required fields and an example payload. |
GET /v1/pricing | Credit pricing: $1/credit, per-song cost (human vs AI), discounted bulk bundles, and auto-reload. Public. |
Profile & credits
| Endpoint | Description |
|---|---|
GET /v1/me | Profile of the authenticated user. |
GET /v1/me/credits?transactions=N | Credit balance, lifetime aggregates, and recent transactions. |
GET /v1/me/autoreload | Current auto-reload configuration. |
POST /v1/me/autoreload | Enable, disable, or reconfigure auto-reload (enabled, package_id/quantity, payment_method_id?, threshold_credits?). |
POST /v1/credits/checkout | Create a Stripe checkout session to buy credits (credits for a custom amount, or package_id for a discounted bundle; optional save_payment_method). |
Files & uploads
| Endpoint | Description |
|---|---|
POST /v1/files | Upload a small file as JSON base64. |
POST /v1/files/from-url | Import a file from a public URL. |
POST /v1/uploads | Create a chunked upload session for large local files. |
Audio intelligence
| Endpoint | Description |
|---|---|
POST /v1/audio/ai-detection | AI Song Detector result for an uploaded file. |
POST /v1/audio/acr-check | Registry-match (Pex Search / Identify Music) check. |
POST /v1/cover-art | Generate or iteratively edit AI album art. |
Drafts & releases
| Endpoint | Description |
|---|---|
POST /v1/drafts | Upsert a work-in-progress release snapshot. |
GET /v1/releases?limit=100 | Recent releases for the authenticated user. |
POST /v1/releases | Submit a release for distribution. Returns 201. |
GET /v1/releases/:id | Merged metadata for a release. |
GET /v1/releases/:id/status | Store delivery + aggregate status. |
GET /v1/releases/:id/job | Background processing job state and errors. |
Errors
Errors use a stable, machine-readable envelope:
{ "type": "validation_error", "code": "email_taken", "message": "..." }type is the error family, code is a machine-readable cause (e.g.
email_taken, invalid_credentials, pkce_required), and message is
human-readable.
| Family | HTTP | Notes |
|---|---|---|
invalid_request_error | 400 | Malformed request. |
authentication_error | 401 | Missing or invalid access token. |
permission_error | 403 | Not allowed for this account. |
not_found_error | 404 | No such resource. |
conflict_error | 409 | e.g. email_taken. |
validation_error | 422 | The platform rejected the content (metadata policy, weak password…). |
locked_error | 423 | account_locked. |
rate_limit_error | 429 | Honor the Retry-After header / retryAfterSeconds. |
oauth_error | 400/401 | Token endpoint errors (invalid_grant, …). |
upstream_error | 502 | The platform returned something unexpected; safe to retry with backoff. |
api_error | 500 | Unexpected gateway error. |
Provenance
Partners can tag requests with the X-Once-Provenance header (e.g. AIMD).
The tag is forwarded to the platform and recorded on releases for analytics.
See Authentication for partner onboarding.
Questions or partner access: tech@once.app.