Platform: tenants, your artifact domain, statements
The Platform plan ($199 a month) is for products that run their own customers' code on Shotcup. Each of your customers can be a tenant: runs, sandboxes and uploads belong to it, it can have its own quotas within your plan, and you can read its usage for your own billing.
Create a tenant
curl https://shotcup.dev/api/v1/tenants \
-H "Authorization: Bearer $SHOTCUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"externalId": "cus_123", "name": "Acme Inc.", "metadata": {"crm": "4711"},
"quotas": {"maxConcurrent": 5, "runsPerMonth": 100000, "computeHoursPerMonth": 10}}'externalId is your own id for the customer (1-64 letters, digits and . _ : @ -), unique among your tenants. An account holds up to 1,000 tenants; more is a contract term. Metadata is up to 20 string entries for your own use.
Quotas are optional and each at most your plan's number: maxConcurrent (1-100), runsPerMonth (0-5,000,000), computeHoursPerMonth (0-300), memory ("standard" refuses the tenant's memory: "large" runs) and retentionDays (1-90; how long its runs' history and artifact links last, 90 days by default). A tenant without a quota shares your account's limit. A tenant's run always counts against your account's allowance too.
Run as a tenant
Two ways, and you can mix them:
- The tenant header. Your account key with
Shotcup-Tenant: cus_123(the external id, or the tenant's id) acts for that tenant on the run, sandbox, upload and artifact routes. One key serves all your customers from your backend. - A tenant key.
POST /api/v1/tenants/cus_123/keyswith{"name": "production"}returns a key (shown once) that acts only for that tenant. Hand it to an environment you do not fully trust, such as your customer's own deployment. A tenant holds up to 10 live keys; an account creates up to 600 tenant keys an hour.
A tenant key, or a request naming a tenant, can run code, manage the tenant's sandboxes and workspace files, upload files and mint links to the tenant's own artifacts. It cannot read another tenant's runs, sandboxes, uploads or artifacts (they answer 404), nor the account: /api/v1/me, API keys and tenant management answer 403 tenant-forbidden. The MCP server takes account keys only. Your account key without the header sees every tenant's runs and sandboxes; each run and sandbox carries its tenantId.
Quota denials
A run past a tenant's own quota is a 429 whose error.kind names it and whose error.tenant is the external id, so you can tell your customer's limit from your plan's:
| kind | meaning |
|---|---|
tenant-concurrency-limit | the tenant's maxConcurrent runs are in flight |
tenant-allowance-runs | the tenant used its runsPerMonth this month |
tenant-allowance-compute | the tenant used its computeHoursPerMonth this month |
tenant-large-memory-not-allowed | the tenant is limited to memory: "standard" |
Your plan's own denials (concurrency-limit, allowance-runs, ...) still apply to every tenant run. Months are UTC calendar months.
Usage, suspension and deletion
GET /api/v1/tenantslists tenants with this month's runs and compute (?limit=up to 100,?cursor=for the next page).GET /api/v1/tenants/cus_123/usage?month=2026-10returns one tenant's runs and compute-hours in a month, for billing your customer.PATCH /api/v1/tenants/cus_123changesname,metadata(replaced whole),quotas(merged;nullremoves one) andsuspended. A suspended tenant's keys and header answer403 tenant-suspendedand its artifact links 404 until you resume it.DELETE /api/v1/tenants/cus_123revokes its keys, deletes its saved sandboxes and frees the external id; its run history stays until it expires and still counts in your usage.
The dashboard's Platform section does all of this too.
Artifact links on your own domain
Artifact links normally live on shotcup.page. A Platform account can serve them from one host of its own, such as artifacts.example.com (a subdomain; more hosts are a contract term):
POST /api/v1/domainswith{"host": "artifacts.example.com"}. The answer lists the DNS records to set: a TXT record at_shotcup-challenge.artifacts.example.comthat proves the host is yours, and a CNAME that points the host at Shotcup.POST /api/v1/domains/artifacts.example.com/verifyonce the records are live. The domain becomesverified; Shotcup then attaches it to its hosting, and it becomesactive.- From then on, artifact links of your runs and your tenants' runs use
https://artifacts.example.com/a/.... Links issued before keep working.
Your host serves only your account's artifacts, with the same protections as shotcup.page: no cookies, X-Content-Type-Options: nosniff, no referrer, and HTML and SVG in a sandbox without your origin. Everything else on it answers 404. DELETE /api/v1/domains/artifacts.example.com removes it.
Monthly statements and invoices
GET /api/v1/statementslists months;GET /api/v1/statements/2026-10returns the month as JSON with your plan fee, usage, overage and a line per tenant plus your own usage;?format=csvand?format=html(a printable statement) too, and?tenant=cus_123for one tenant's usage. The current month is a running statement; a month is final from 01:00 UTC on the 1st of the next.PUT /api/v1/billing/detailssets the legal name, billing email, address and VAT or tax ID printed on your invoices.- Platform is invoiced monthly in arrears (the plan fee plus the month's overage, net 30) from the final statement, once invoicing is switched on for your account.
This page as Markdown:/docs/platform.md