blawgy-com Team and billing API
Teammates, invites and billing.
Teammates, invites and billing.
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/blawgy-com:blawgy-com-team-and-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: Blawgy Team and billing API
version: 1.0.0
description: 'The Blawgy API: everything the Blawgy dashboard and MCP server can do, over HTTPS. Every endpoint is also an MCP tool (`x-mcp-tool`); both transports share keys, site scoping, plan gating, rate limits and the audit log.
**Authentication.** `Authorization: Bearer blk_live_...` with an API key from Settings > Account > AI agents in the Blawgy dashboard (or an OAuth access token issued for this host). Keys are server-side only: there is no CORS on /v1, except the keyless public content endpoints under `/public`.
**Arguments.** GET endpoints take theirs as query parameters; POST, PATCH, PUT and DELETE take a JSON body (`Content-Type: application/json`), and their query string carries only `dryRun`. Unknown arguments are a 400, never silently dropped.
**Errors.** Every non-2xx answer is `{ "error": { "code", "message", "details"?, "requestId" } }`. Every response carries `Request-Id`.
**Pagination.** Lists answer `{ data, nextCursor, total? }` and take `?limit=` and `?cursor=` (the previous page''s `nextCursor`). `limit` is capped per endpoint (never above 200); a larger value is clamped to the cap.
**Idempotency.** Send `Idempotency-Key` on POST, PATCH, PUT or DELETE to make a retry safe for 24 hours: the same key and request replays the stored answer (`Idempotent-Replayed: true`); the same key with a different request is a 422.
**Dry runs.** `?dryRun=true` on any write runs every gate (auth, scope, plan, validation) and returns a one-line summary without doing anything.
**Rate limits.** 240 calls a minute and 6,000 a day per key, shared with MCP. Responses carry `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`; a 429 adds `Retry-After`. The public content endpoints need no key and are limited per client IP instead.
**Async work.** Research, writing, scans and syncs return as soon as the job is queued; poll `GET /sites/{site}/jobs/{kind}`.
**Versioning.** `/v1` is frozen for breaking changes; additive changes ship freely.'
termsOfService: https://blawgy.com/terms
contact:
url: https://blawgy.com/developers
servers:
- url: https://app.blawgy.com/v1
security:
- bearerAuth: []
tags:
- name: Team and billing
description: Teammates, invites and billing.
paths:
/sites/{site}/billing:
get:
operationId: get_billing
summary: Current plan and billing status
description: The site's subscription (plan, status, trial, renewal date, cancel-at-period-end, frozen for failed payment, the latest Stripe invoice link and, when frozen, the unpaid invoice to pay) and the plans available to move to. Read only. Hidden for white-label customers, whose partner bills them. Use get_upgrade_link to change plans in the browser.
tags:
- Team and billing
x-mcp-tool: get_billing
x-access: read
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/sites/{site}/billing/upgrade-link:
post:
operationId: get_upgrade_link
summary: Get a checkout or billing portal link
description: 'Returns a URL a HUMAN opens in the browser. Without `planId`: the Stripe billing portal for the site''s existing subscription (card, invoices, plan changes). With `planId` (from get_billing plans): a Stripe Checkout page to START a subscription for a site that has none; a site that already has a live subscription gets the billing portal link instead (change the plan there), never a second checkout. Nothing is charged by this tool itself. Hidden for white-label customers.'
tags:
- Team and billing
x-mcp-tool: get_upgrade_link
x-access: write
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
- $ref: '#/components/parameters/IdempotencyKey'
- $ref: '#/components/parameters/DryRun'
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
Idempotent-Replayed:
$ref: '#/components/headers/Idempotent-Replayed'
content:
application/json:
schema:
oneOf:
- type: object
additionalProperties: true
- type: object
description: 'With ?dryRun=true: every gate passed, nothing ran.'
properties:
dryRun:
type: boolean
const: true
tool:
type: string
summary:
type: string
valid:
type: boolean
required:
- dryRun
- summary
- valid
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'402':
$ref: '#/components/responses/402'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'409':
$ref: '#/components/responses/409'
'422':
$ref: '#/components/responses/422'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
planId:
type: string
maxLength: 120
description: Start checkout for this plan on a site with no live subscription; otherwise the portal link is returned.
additionalProperties: false
/sites/{site}/team:
get:
operationId: list_team
summary: List teammates and invitations
description: Everyone with access to this site (owner and accepted members) plus every invitation and its state (pending, accepted, revoked, email sent or failed). Invite links are not listed; invite_teammate returns one. Read only.
tags:
- Team and billing
x-mcp-tool: list_team
x-access: read
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/sites/{site}/team/invites:
post:
operationId: invite_teammate
summary: Invite a teammate
description: Emails an invitation to work on this site (the invitee gets the link by email; it is never returned here). Anyone on the site team can invite. Re-inviting the same address resends the same invitation. `emailDomain` restricts the link to addresses at one company.
tags:
- Team and billing
x-mcp-tool: invite_teammate
x-access: destructive
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
- $ref: '#/components/parameters/IdempotencyKey'
- $ref: '#/components/parameters/DryRun'
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
Idempotent-Replayed:
$ref: '#/components/headers/Idempotent-Replayed'
content:
application/json:
schema:
oneOf:
- type: object
additionalProperties: true
- type: object
description: 'With ?dryRun=true: every gate passed, nothing ran.'
properties:
dryRun:
type: boolean
const: true
tool:
type: string
summary:
type: string
valid:
type: boolean
required:
- dryRun
- summary
- valid
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'402':
$ref: '#/components/responses/402'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'409':
$ref: '#/components/responses/409'
'422':
$ref: '#/components/responses/422'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
format: email
maxLength: 254
emailDomain:
type: string
maxLength: 253
description: Only people at this domain can accept, for example "acme.com".
required:
- email
additionalProperties: false
/sites/{site}/team/invites/{inviteId}:
delete:
operationId: revoke_invite
summary: Revoke an invitation
description: Withdraws a pending invitation so its link stops working. It does not remove a teammate who already accepted.
tags:
- Team and billing
x-mcp-tool: revoke_invite
x-access: destructive
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
- name: inviteId
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 120
- $ref: '#/components/parameters/IdempotencyKey'
- $ref: '#/components/parameters/DryRun'
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
Idempotent-Replayed:
$ref: '#/components/headers/Idempotent-Replayed'
content:
application/json:
schema:
oneOf:
- type: object
additionalProperties: true
- type: object
description: 'With ?dryRun=true: every gate passed, nothing ran.'
properties:
dryRun:
type: boolean
const: true
tool:
type: string
summary:
type: string
valid:
type: boolean
required:
- dryRun
- summary
- valid
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'402':
$ref: '#/components/responses/402'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'409':
$ref: '#/components/responses/409'
'422':
$ref: '#/components/responses/422'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
/sites/{site}/team/invites/{inviteId}/resend:
post:
operationId: resend_invite
summary: Resend an invitation
description: Sends the invitation email again for a pending invite from list_team. At most once per hour per invitation.
tags:
- Team and billing
x-mcp-tool: resend_invite
x-access: destructive
x-min-plan: null
x-partner-only: false
security:
- bearerAuth: []
parameters:
- name: site
in: path
required: true
schema:
type: string
minLength: 1
description: The site, as its domain (example.com). See GET /sites.
- name: inviteId
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 120
- $ref: '#/components/parameters/IdempotencyKey'
- $ref: '#/components/parameters/DryRun'
responses:
'200':
description: The result, exactly what the matching MCP tool returns.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
RateLimit-Limit:
$ref: '#/components/headers/RateLimit-Limit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimit-Remaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimit-Reset'
Idempotent-Replayed:
$ref: '#/components/headers/Idempotent-Replayed'
content:
application/json:
schema:
oneOf:
- type: object
additionalProperties: true
- type: object
description: 'With ?dryRun=true: every gate passed, nothing ran.'
properties:
dryRun:
type: boolean
const: true
tool:
type: string
summary:
type: string
valid:
type: boolean
required:
- dryRun
- summary
- valid
'400':
$ref: '#/components/responses/400'
'401':
$ref: '#/components/responses/401'
'402':
$ref: '#/components/responses/402'
'403':
$ref: '#/components/responses/403'
'404':
$ref: '#/components/responses/404'
'409':
$ref: '#/components/responses/409'
'422':
$ref: '#/components/responses/422'
'429':
$ref: '#/components/responses/429'
'500':
$ref: '#/components/responses/500'
components:
responses:
'429':
description: Rate limited; `Retry-After` says when to try again.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: '`idempotency_key_reused`: the Idempotency-Key was used for a different request.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'402':
description: The site is read-only until its billing is sorted out.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: The bearer token is missing, unknown, expired or revoked.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Something failed on our side. The `requestId` finds it in our logs.
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict, including `idempotency_in_progress` and `idempotency_secret_not_replayable` (a retry of a call that returned a one-time secret).
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: 'The credential may not do this: read-only key, wrong scope, plan too low (`upgrade_required`), owner only.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: 'Not found: the route, the site (`site_not_found`) or the thing inside it.'
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'400':
description: The request is malformed or the arguments failed validation (`details.issues` lists them).
headers:
Request-Id:
$ref: '#/components/headers/Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
schema:
type: string
maxLength: 255
description: Any unique string (a UUID works). A retry with the same key and request inside 24 hours replays the stored answer instead of running again.
DryRun:
name: dryRun
in: query
required: false
schema:
type: boolean
description: 'true: run every gate and validation, return a summary, change nothing.'
headers:
Request-Id:
schema:
type: string
description: Identifies this request in our logs and audit trail. Quote it to support.
RateLimit-Remaining:
schema:
type: integer
description: Calls left in the current window.
RateLimit-Reset:
schema:
type: integer
description: Seconds until the window resets.
Idempotent-Replayed:
schema:
type: boolean
description: true when this answer was replayed from an earlier request with the same Idempotency-Key.
RateLimit-Limit:
schema:
type: integer
description: Calls allowed in the current window.
schemas:
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- requestId
properties:
code:
type: string
description: Stable machine-readable reason (site_not_found, invalid_request, upgrade_required, rate_limited, ...).
message:
type: string
details:
type: object
additionalProperties: true
description: 'Extra context; validation errors carry `issues: [{ path, code, message }]`.'
requestId:
type: string
description: Same as the Request-Id header.
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: blk_live_... API key or OAuth access token
description: An API key from Settings > Account > AI agents in the Blawgy dashboard. Read keys may only call GET endpoints; keys scoped to specific sites cannot reach other sites or change the account.