Ultralytics Billing API
Assinaturas (Stripe; Asaas como alternativa)
Assinaturas (Stripe; Asaas como alternativa)
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/ultralytics:ultralytics-billing-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Telenor Sverige Billing API
version: '1.0'
description: 'Operations tagged Billing across 2 of this provider''s published API definitions: full_openapi.yml, ultralytics-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://apipj.com.br
- url: https://platform.ultralytics.com
description: Production
tags:
- name: Billing
description: Assinaturas (Stripe; Asaas como alternativa)
paths:
/v1/billing/checkout:
post:
summary: Inicia a assinatura de um plano pago
tags:
- Billing
description: 'Provedor em `GET /v1/plans` → `billing.provider`. **Stripe:** cria (ou reaproveita, com `reused: true`) uma Checkout Session de assinatura mensal e devolve `{url, plan, value, reused, return_supported: true}`; `url` é a página do Stripe (checkout.stripe.com), que pede o cartão e o CPF/CNPJ (nada disso passa por esta API) e volta para `/painel?pagamento=retorno&session_id=…` (ou `/painel?pagamento=cancelado`). Sem `cpf_cnpj`. Em produção com o Stripe em modo de teste, só contas liberadas assinam: as demais recebem 403 `checkout_indisponivel` ("Assinaturas abrindo em breve"); preço do Stripe divergente de `config/plans.json`: 503 `checkout_indisponivel`. **Asaas:** cria (ou reaproveita) a assinatura no Asaas e devolve `{url, plan, value, reused, return_supported}`: `url` é a fatura hospedada, onde o cliente informa o cartão (nenhum dado de cartão passa por esta API). A assinatura é criada com retorno automático para `/painel?pagamento=retorno` (`return_supported: true`: abra a fatura na mesma aba); se o Asaas recusar o retorno (site não cadastrado na conta Asaas), ela é refeita sem ele e `return_supported` vem `false` (abra a fatura em outra aba e mantenha o painel consultando `POST /v1/billing/sync`). Com `reused: true` a fatura pendente do mesmo plano foi reaproveitada. Exige CPF/CNPJ: se o cadastro não tem, envie `cpf_cnpj` no corpo (fica gravado na conta). Pedido anterior já pago no Asaas e ainda não ativado: 409 `checkout_already_paid` (o plano é ativado na hora e nada é recriado). Conta em revisão por contestação de pagamento: 403 `account_under_review`. Pedidos simultâneos da mesma conta são atendidos um de cada vez (o segundo do mesmo plano reaproveita a fatura do primeiro). Limite: 10 por minuto por IP e, por usuário, 6 por minuto e 30 por hora (429 `rate_limited` com `Retry-After`). Requer o header `X-Requested-With: apipj`.'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan
additionalProperties: false
properties:
plan:
type: string
minLength: 1
maxLength: 30
cpf_cnpj:
type: string
maxLength: 24
description: CPF ou CNPJ do titular (só é usado se a conta ainda não tem um)
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: postV1BillingCheckout
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/v1/billing/pending:
get:
summary: Pagamento pendente do pedido em andamento
tags:
- Billing
description: '`{pending: null}` ou `{pending: {plan, plan_name, value, invoice_url, due_date, created_at, return_supported}}`: a fatura ainda não paga da assinatura criada pelo checkout (consulta o Asaas; guardada por 30 s por usuário). `invoice_url` reaproveita a mesma fatura ("Continuar pagamento"). Falha do Asaas: 502 `billing_unavailable`. `GET /v1/me` traz `checkout.pending` (só o banco local) para decidir se vale consultar esta rota.'
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: getV1BillingPending
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/v1/billing/cancel-pending:
post:
summary: Cancela o pedido ainda não pago
tags:
- Billing
description: 'Remove no Asaas a assinatura criada pelo checkout que ainda não foi paga e limpa o pedido: `{cancelled: true, plan, plan_name, plan_valid_until}` (o plano atual da conta, que não muda). 409 `no_pending_checkout` se não há pedido pendente; 409 `checkout_already_paid` se o Asaas já confirmou o pagamento (o plano é ativado na hora; para não renovar, use `POST /v1/billing/cancel`). Falha do Asaas: 502 `billing_unavailable`, nada muda. Numa troca de plano a assinatura anterior já foi removida no checkout: o plano atual segue até `plan_valid_until`, sem renovação. Requer o header `X-Requested-With: apipj`.'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties: {}
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: postV1BillingCancelPending
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/v1/billing/sync:
post:
summary: Confere o pagamento do pedido no Asaas e ativa o plano
tags:
- Billing
description: 'Para a volta do Asaas (`/painel?pagamento=retorno`) e para o painel com pedido em andamento: reconsulta no Asaas as cobranças da assinatura da conta e, se o Asaas diz `CONFIRMED`/`RECEIVED`, ativa o plano pelo mesmo caminho do webhook (idempotente com ele: uma só ativação). Nunca ativa sem a confirmação do Asaas. Devolve `{status, plan, plan_name, plan_valid_until, limits: {rpm, monthly_quota}, activated, checked}`: `status` = `active` (plano pago vigente e nenhum pedido pendente), `pending` (pedido aguardando o pagamento; `plan` é o plano pedido) ou `none` (nenhum pedido e plano gratuito); `activated` = esta chamada ativou o plano; `checked` = o Asaas foi consultado nesta chamada (`false`: sem pedido pendente, consulta recente, teto de consultas ou Asaas indisponível; a resposta sai do estado local, sem erro). Limite: 30 por minuto por usuário (429 `rate_limited` com `Retry-After`). Requer o header `X-Requested-With: apipj`.'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
session_id:
type: string
minLength: 1
maxLength: 255
description: 'Stripe: o session_id do retorno do Checkout (/painel?pagamento=retorno&session_id=…); precisa ser da conta (senão 403 checkout_session_mismatch)'
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: postV1BillingSync
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/v1/billing/cancel:
post:
summary: Cancela a assinatura (plano vale até o fim do período pago) ou exerce o…
tags:
- Billing
description: 'No provedor que ativou o plano: no Stripe, `cancel_at_period_end` (a assinatura não renova e acaba no fim do período pago); no Asaas, remove a assinatura. O plano continua ativo até `plan_valid_until`; depois cai para o gratuito. Com `{"refund": true}` dentro de `refund_eligible_until` (7 dias da confirmação do primeiro pagamento do plano, CDC art. 49; termos §6.7): estorno da primeira cobrança no mesmo cartão e volta imediata ao gratuito. O estorno é integral quando o uso desde a ativação ficou em até 20% da cota mensal; acima disso é limitado à parte não utilizada (`refund_full: false`, cálculo em `usage` e no e-mail); uso igual ou acima da cota, ou fora das condições, responde 400 `refund_not_eligible` com `reason`. Um pedido de estorno por contratação: pedidos repetidos ou simultâneos recebem 400 `refund_not_eligible` (`ja_estornado`); erro do Asaas responde 502 e o pedido pode ser repetido; sem resposta do Asaas (timeout), 502 com o pedido mantido e orientação para falar com o suporte. Confirmação por e-mail nos dois casos. Requer o header `X-Requested-With: apipj`.'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
refund:
type: boolean
description: 'true = desistência em 7 dias: estorno integral se o uso desde a ativação ficou em até 20% da cota mensal; acima disso, limitado à parte não utilizada (refund_full:false, cálculo em usage); uso igual ou acima da cota: 400 refund_not_eligible (uso_excessivo)'
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: postV1BillingCancel
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/v1/billing/portal:
post:
summary: Portal do cliente do Stripe (cartão e faturas)
tags:
- Billing
description: 'Plano pago ativado pelo Stripe: devolve `{url}` de uma sessão do portal do cliente do Stripe (billing.stripe.com, válida por pouco tempo; abra na hora), com volta para `/painel`. O portal serve só para trocar o cartão e ver as faturas; cancelar e desistir continuam em `POST /v1/billing/cancel`. Sem assinatura no Stripe: 400 `no_subscription`. Falha do Stripe: 502 `billing_unavailable`. Requer o header `X-Requested-With: apipj`.'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
properties: {}
security:
- cookie: []
responses:
'200':
description: Default Response
operationId: postV1BillingPortal
x-operation-id-source: derived
servers:
- url: https://apipj.com.br
/api/billing/transactions:
get:
summary: View transaction history
tags:
- Billing
operationId: get_api_billing_transactions
description: Returns credit purchases, training charges, and other billing transactions.
parameters:
- name: from
in: query
required: false
description: Earliest transaction timestamp
schema:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
- name: to
in: query
required: false
description: Latest transaction timestamp
schema:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
responses:
'200':
description: Transaction history
content:
application/json:
schema:
$ref: '#/components/schemas/BillingTransactionsResponse'
'400':
description: Invalid date range
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing or invalid authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Workspace access denied
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Transaction history unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
x-codeSamples:
- label: Python SDK
lang: Python
source: 'from ultralytics_platform import Platform
client = Platform() # Reads ULTRALYTICS_API_KEY
response = client.billing.transactions()
print(response)'
security:
- BearerAuth: []
servers:
- url: https://platform.ultralytics.com
description: Production
/api/billing/usage-summary:
get:
summary: View plan and usage
tags:
- Billing
operationId: get_api_billing_usage_summary
description: Returns plan status, storage usage, training credit, feature access, seats, and billing totals.
responses:
'200':
description: Plan and usage summary
content:
application/json:
schema:
$ref: '#/components/schemas/BillingUsageSummaryResponse'
'401':
description: Missing or invalid authentication
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Workspace access denied
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Usage summary unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
x-codeSamples:
- label: Python SDK
lang: Python
source: 'from ultralytics_platform import Platform
client = Platform() # Reads ULTRALYTICS_API_KEY
response = client.billing.usage_summary()
print(response)'
security:
- BearerAuth: []
servers:
- url: https://platform.ultralytics.com
description: Production
components:
schemas:
BillingUsageSummaryResponse:
type: object
properties:
plan:
type: object
properties:
planId:
type: string
enum:
- free
- pro
- enterprise
description: User subscription tier
name:
type: string
status:
type: string
enum:
- active
- past_due
cancelAtPeriodEnd:
type: boolean
paymentFailedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
billingCycle:
type: string
enum:
- monthly
- yearly
currentPeriodEnd:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
enterpriseLicenseEnd:
type: string
licenseExpired:
type: boolean
required:
- planId
- name
- status
- cancelAtPeriodEnd
additionalProperties: false
metrics:
type: array
items:
type: object
properties:
metricId:
type: string
const: storage_bytes
kind:
type: string
const: GAUGE
period:
type: string
const: NONE
limit:
type: number
used:
type: number
remaining:
type: number
overageAllowed:
type: boolean
required:
- metricId
- kind
- period
- limit
- used
- remaining
- overageAllowed
additionalProperties: false
trainingCredit:
type: object
properties:
monthlyGrant:
type: number
balanceAvailable:
type: number
required:
- monthlyGrant
- balanceAvailable
additionalProperties: false
features:
type: object
properties:
privateProjects:
type: boolean
teams:
type: boolean
enterpriseLicense:
type: boolean
required:
- privateProjects
- teams
- enterpriseLicense
additionalProperties: false
creditsCents:
type: number
paidSeats:
type: number
currentSeats:
type: number
maxSeats:
type: number
nextInvoiceCents:
type: number
required:
- plan
- metrics
- trainingCredit
- features
- creditsCents
additionalProperties: false
description: Workspace plan, limits, and usage
BillingTransactionsResponse:
type: object
properties:
transactions:
type: array
items:
type: object
properties:
id:
type: string
type:
type: string
enum:
- signup
- purchase
- subscription
- monthly_grant
- training
- deployment
- annotation
- refund
- adjustment
- promo
- auto_topup
- auto_topup_failed
- pro_credit_expiry
amountCents:
type: number
balanceAfter:
type: number
modelId:
type: string
datasetId:
type: string
apiKeyId:
type: string
runId:
type: string
gpuType:
type: string
gpuDisplayName:
type: string
period:
type: string
createdAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
receiptUrl:
type:
- string
- 'null'
model:
anyOf:
- type: object
properties:
name:
type: string
slug:
type: string
projectSlug:
type: string
username:
type: string
datasetId:
type: string
gpuType:
type: string
gpuDisplayName:
type: string
startedAt:
type: string
format: date-time
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
required:
- name
- slug
- projectSlug
- username
additionalProperties: false
- type: 'null'
required:
- id
- type
- amountCents
- balanceAfter
- createdAt
additionalProperties: false
required:
- transactions
additionalProperties: false
description: Workspace credit transaction history
ErrorResponse:
type: object
properties:
error:
type: string
description: Error message
example: Invalid request
required:
- error
additionalProperties: false
description: Standard error response
securitySchemes:
bearer:
type: http
scheme: bearer
description: 'Authorization: Bearer <chave>'
apiKey:
type: apiKey
in: header
name: X-API-Key
cookie:
type: apiKey
in: cookie
name: __Host-apipj_session
BearerAuth:
type: http
scheme: bearer
description: API key starting with `ul_`. Create one at platform.ultralytics.com under Settings > API Keys.
externalDocs:
description: Full documentation with guides and examples
url: https://docs.ultralytics.com/platform/api
x-refined-from:
- full_openapi.yml
- ultralytics-openapi.yml