blawgy-com Team and billing API

Teammates, invites and billing.

Operations 6

GET /sites/{site}/billing Current plan and billing status #
GET /sites/{site}/team List teammates and invitations #
POST /sites/{site}/team/invites Invite a teammate #
DELETE /sites/{site}/team/invites/{inviteId} Revoke an invitation #
POST /sites/{site}/team/invites/{inviteId}/resend Resend an invitation #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • 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.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/blawgy-com:blawgy-com-team-and-billing-api"
All apis
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.

Get an API 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 Specification

blawgy-com-team-and-billing-api-openapi.yml Raw ↑
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.