Frase Usage API

The Usage API from Frase — 2 operation(s) for usage.

GitHub OpenAPI

Operations 2

GET /me Get account identity #
GET /usage Get usage and quota #

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/frase-io:frase-io-usage-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

frase-io-usage-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Frase Usage API
  version: 1.0.0
  description: 'The Frase API provides programmatic access to your SEO content platform. Use it to manage content, research, audits, AI visibility tracking, and more. ## Authentication


    All API requests require authentication using an API key. Include your key in the `X-API-KEY` header:


    ```

    X-API-KEY: sk_live_your_api_key_here

    ```


    For legacy compatibility, the `token` header is also supported. ## Rate Limits


    Three independent limits apply, each with its own headers and error code. Headers are returned on `429` responses, not on successful ones. **Per-minute burst** - 60/min on trial and Starter, 120 Professional, 300 Scale, 1,000 Enterprise. Error code `rate_limit_exceeded`. - `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (epoch seconds)


    **Sustained hourly ceiling** - 2,000/hour trial, 3,000 Starter, 5,000 Professional, 15,000 Scale, 50,000 Enterprise. Error code `hourly_limit_exceeded`. - `X-RateLimit-Hourly-Limit`, `X-RateLimit-Hourly-Remaining`, `X-RateLimit-Hourly-Reset` (epoch seconds)


    **Monthly request budget** - error code `monthly_budget_exceeded`, headers `X-Monthly-Limit`, `X-Monthly-Used`, `X-Monthly-Remaining`. Every `429` carries `Retry-After` in seconds. On the hourly ceiling this can be up to 3,600, so clients should honour it rather than retrying on a short fixed backoff - a retry sooner than `Retry-After` cannot succeed. ## Errors


    The API uses standard HTTP status codes and returns errors in a consistent format:


    ```json

    {

    "error": {

    "type": "authentication_error",

    "code": "invalid_api_key",

    "message": "Invalid API key provided.",

    "doc_url": "https://docs.frase.io/api/errors#invalid_api_key"

    }

    }

    ```


    ## Changelog


    Breaking changes are listed here, newest first. "Breaking" means a field that was always present with a value can now be `null`, or an existing value now means something different — not that a field was removed or renamed. Additive fields are not listed. ### 2026-08-31 — Fact `sources[]` may omit `url`, and minted facts default to `approved`


    - `GET /briefs/{id}/facts`, `PATCH /briefs/{id}/facts/{factId}` → a `sources[]` entry may now carry only `title`, with no `url` or `domain`. Research names a publisher far more often than it captures a link (793 of 801 plan-evidence items in production), and those names were previously discarded rather than returned. Read `url` defensively. - `GET /briefs/{id}/facts` → `approval` on a newly minted fact is now `approved` rather than `pending`. A client polling for `pending` facts to review will see far fewer; rejection is unchanged and remains permanent. Facts the writer asserted in its own output (`provenance: generated`) are still minted `pending`. ### 2026-08-24 — Content Guard''s hasPublishedUrl is now recoverability, not the stored URL


    - `GET /content/{id}/monitoring` → `hasPublishedUrl`: was a judgment on the STORED URL (false for a relative path even when the page was live). It now answers "could Guard watch this article right now" — the stored URL when absolute, or an address the server recovers (CMS inventory; FraseCMS re-derivation from current settings when a live published post exists). `true` no longer implies the stored URL itself is absolute, and a FraseCMS article published before domain setup flips to `true` when setup finishes, with no re-publish. It remains exactly the condition enabling enforces. - `publishedUrlIssue` is now the RESIDUAL after recovery failed, not a raw-column classification — "not_absolute" can also mean the FraseCMS post is not live or FraseCMS is disabled for the site. - `POST /content/{id}/publish` → `url` (frase_cms): now derived from the site''s current CMS settings rather than the adapter''s host-of-the-moment value; the same URL is stored on the content row and sent in the content.published webhook.'
  contact:
    name: Frase Support
    url: https://frase.io
    email: support@frase.io
  license:
    name: Proprietary
    url: https://www.frase.io/company/terms
servers:
- url: https://next.frase.io/api/v1
  description: Production
- url: /api/v1
  description: This host
security:
- ApiKeyAuth: []
- BearerAuth: []
tags:
- name: Usage
paths:
  /me:
    get:
      operationId: getMe
      summary: Get account identity
      description: 'The organization this API key belongs to. Built for integration surfaces that label a connection (a Zapier connection label, an MCP client asking "which Frase account is this?").


        This endpoint does NOT consume a metered request, and needs no particular scope beyond a valid key. Both are deliberate: connection tests re-run on a schedule, so an account would otherwise pay quota for merely being connected, and a key holding only write scopes still belongs to an account its owner needs to recognize.


        `organization_name` can be null for a short window after the key was first cached; retry on the next test.'
      tags:
      - Usage
      security:
      - ApiKeyAuth: []
      responses:
        '200':
          description: The calling key's organization.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      organization_id:
                        type: string
                        format: uuid
                        description: The organization the API key is scoped to.
                      organization_name:
                        type:
                        - string
                        - 'null'
                        description: The organization's display name. Null only briefly for keys cached before this field existed.
                    required:
                    - organization_id
                    - organization_name
        '401':
          description: Missing or invalid API key.
  /usage:
    get:
      operationId: getUsage
      summary: Get usage and quota
      description: 'What each pool has used, its limit, when it refills, and what has recently been refused.


        This endpoint does NOT consume a metered request, and needs no particular scope beyond a valid key. Both are deliberate: the callers who most need to read their quota are the ones who have run out, and a key holding only write scopes still has to be able to discover why its writes started failing.


        Use it to pace work before a large batch, and to interpret a 429 after one.


        ### 2026-10-22 - resources adds ai_visibility_prompts


        Additive: `resources` gains an `ai_visibility_prompts` key with the same shape as `domains` and `seats` (tracked AI Visibility prompts against the organization''s active-prompt cap; no `resets_at`). A client that iterates every resource key sees one more entry; no existing key or field changed.'
      tags:
      - Usage
      security:
      - ApiKeyAuth: []
      parameters:
      - name: include_denials
        in: query
        description: Set to false to omit recent_denials.
        schema:
          type: boolean
          default: true
      responses:
        '200':
          description: Current usage, limits and recent denials
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      plan:
                        type: string
                      subscription_status:
                        type: string
                      subscription_blocked:
                        type: boolean
                        description: 'True when the subscription itself blocks work, regardless of remaining quota: every pool can read healthy and every call still fail. The remedy differs from an exhausted pool - resubscribe, rather than wait for a reset or upgrade.'
                      meters:
                        type: object
                        description: 'Consumption pools that refill when the usage window rolls. Keys: articles, audit_pages, ai_prompts, research, api_requests, hero_images, diagrams.'
                        additionalProperties:
                          $ref: '#/components/schemas/UsageMeter'
                      resources:
                        type: object
                        description: 'Standing allowances that do not refill, so they carry no resets_at. Keys: domains, seats, ai_visibility_prompts (tracked AI Visibility prompts against the organization''s active-prompt cap).'
                        additionalProperties:
                          $ref: '#/components/schemas/UsageResource'
                      recent_denials:
                        type: array
                        items:
                          $ref: '#/components/schemas/UsageDenial'
                  request_id:
                    type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    UsageResource:
      type: object
      properties:
        used:
          type: integer
        limit:
          type:
          - integer
          - 'null'
        remaining:
          type:
          - integer
          - 'null'
        unlimited:
          type: boolean
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
            code:
              type: string
            message:
              type: string
            param:
              type: string
            doc_url:
              type: string
        request_id:
          type: string
    UsageDenial:
      type: object
      properties:
        limit_type:
          type: string
          enum:
          - burst
          - hourly
          - monthly
          - entitlement
          - subscription
          - serp_daily
        operation:
          type:
          - string
          - 'null'
          description: Which pool refused, for entitlement and subscription denials.
        endpoint:
          type:
          - string
          - 'null'
        occurrences:
          type: integer
          description: 'Denials represented, not rows: repeats for the same limit and endpoint inside a short window are collapsed and counted here.'
        last_at:
          type: string
          format: date-time
    UsageMeter:
      type: object
      properties:
        used:
          type: integer
        limit:
          type:
          - integer
          - 'null'
          description: null when the plan grants unlimited use of this pool.
        remaining:
          type:
          - integer
          - 'null'
          description: null when unlimited. Never negative - an over-consumed pool reports 0 rather than a negative number a client might read as headroom.
        unlimited:
          type: boolean
        resets_at:
          type:
          - string
          - 'null'
          format: date-time
          description: 'When this pool refills, or null when there is nothing honest to announce. Null covers three real cases: the reset threshold has passed and the clearing job has not caught up, the subscription status makes the org ineligible for a reset run, and a never-converted trial whose one-time pool never rolls. Treat null as ''unknown'', not ''never''.'
        bonus_credits:
          type: integer
          description: 'Bonus credits already folded into limit. Present only on pools that have them (today: articles, and only when the org holds a balance), absent everywhere else. This is what reconciles remaining with limit - used, which for articles are deliberately different numbers: bonus credits are spent BEFORE the monthly allowance and do not expire with the cycle, so an org past its monthly limit that holds bonus credits genuinely has that many articles left. Recompute the same answer as max(0, (limit - bonus_credits) - used) + bonus_credits.'
  responses:
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: authentication_error
              code: invalid_api_key
              message: Invalid API key. Check that you are using the correct key.
              doc_url: https://docs.frase.io/api/errors#invalid_api_key
            request_id: req_abc123
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: 'API key for authentication. Get your key from Settings > API Keys. You may also send the same key as `Authorization: Bearer <key>` — see BearerAuth.'
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Frase API key (sk_live_* / sk_test_*) or MCP access token (mcp_at_*)
      description: 'Send either your API key or an MCP access token as `Authorization: Bearer <token>`. An API key sent this way is exactly equivalent to sending it in X-API-KEY — same identity, same scopes, same rate limits — so use whichever your HTTP client makes natural. X-API-KEY takes precedence if you somehow send both. Cookie/session auth is intentionally NOT supported on /api/v1/* endpoints.'