honkio-ca OAuth API

OAuth 2.1 authorization server used by MCP clients (Claude, ChatGPT, Gemini) to sign in instead of carrying an API key. Discovery: /.well-known/oauth-authorization-server

Operations 4

GET /oauth/authorize Start an authorization (browser) #
POST /oauth/token Exchange a code or refresh token for tokens #
POST /oauth/register Register a client dynamically (RFC 7591) #
POST /oauth/revoke Revoke a grant by one of its tokens (RFC 7009) #

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/honkio-ca:honkio-ca-oauth-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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

honkio-ca-oauth-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: HonkIO OAuth API
  description: 'Canadian-focused SMS gateway API.


    ## Canadian Compliance

    - **CASL**: All commercial messages require consent. Use `/v1/compliance/consents` to record.

    - **DNCL**: CRTC Do Not Call List checking is coming soon (not yet enforced).

    - **PIPEDA / Quebec Law 25**: Data is stored in Canada (ca-central-1). Requests are processed in the United States in transit. Right-to-erasure available.


    ## Authentication

    Provide your API key via `Authorization: Bearer mk_live_...` or `X-API-Key: mk_live_...`.

    Test keys never send, never charge and can''t change live data; they work before your first top-up.


    ## Rate limits

    100 requests per second per account. Every authenticated response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`.


    ## Pagination

    Shape follows the route family, not one convention across the API: documented here rather than changed. Messages listings return `{ data, meta: { page, limit, total, pages } }`. Contacts, Contact Groups, Lists and Verify listings return `{ data, total, limit, offset }`. Compliance consent and opt-out listings accept `page`/`limit` and return `{ data }`, with no total. Account transactions use a cursor: pass `before`, get back `has_more`.'
  version: 1.0.0
  contact:
    name: HonkIO Support
    email: support@honkio.ca
servers:
- url: https://api.honkio.ca
  description: Production
- url: http://localhost:3000
  description: Local development
security:
- apiKey: []
- apiKeyHeader: []
tags:
- name: OAuth
  description: 'OAuth 2.1 authorization server used by MCP clients (Claude, ChatGPT, Gemini) to sign in instead of carrying an API key. Discovery: /.well-known/oauth-authorization-server'
paths:
  /oauth/authorize:
    get:
      summary: Start an authorization (browser)
      tags:
      - OAuth
      description: OAuth 2.1 authorization endpoint. Sends the user to the HonkIO consent screen, then back to redirect_uri with a code. PKCE S256 is required. Client ids may be Client ID Metadata Document URLs (https), dynamically registered ids, or pre-registered ids. A request that fails validation is answered with an error page; it is redirected back with an error only when redirect_uri is loopback or the client is pre-registered.
      parameters:
      - schema:
          type: string
        in: query
        name: response_type
        required: false
        description: Must be code.
      - schema:
          type: string
        in: query
        name: client_id
        required: false
      - schema:
          type: string
        in: query
        name: redirect_uri
        required: false
        description: Must match one registered for the client; loopback URIs match regardless of port.
      - schema:
          type: string
        in: query
        name: scope
        required: false
        description: Space-separated. Omit for the default set (everything except account:manage).
      - schema:
          type: string
        in: query
        name: state
        required: false
        description: At most 512 characters.
      - schema:
          type: string
        in: query
        name: code_challenge
        required: false
        description: 43 to 128 base64url characters (RFC 7636).
      - schema:
          type: string
        in: query
        name: code_challenge_method
        required: false
        description: Must be S256.
      - schema:
          type: string
        in: query
        name: resource
        required: false
        description: RFC 8707 resource indicator, the MCP endpoint URL.
      security: []
      responses:
        '302':
          description: Redirect to the consent screen. A request that fails validation is redirected back to redirect_uri with an error, state and iss only when that URI is loopback or the client is pre-registered.
          headers:
            Location:
              schema:
                type: string
        '400':
          description: An HTML page (never a redirect) when client_id or redirect_uri cannot be trusted, when state is longer than 512 characters, or when a dynamically registered or metadata-document client sends a request that fails validation with a redirect_uri that is not loopback.
          content:
            text/html:
              schema:
                type: string
        '429':
          description: 'slow_down: 30 requests a minute from one address.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
      operationId: getOauthAuthorize
      x-operation-id-source: derived
  /oauth/token:
    post:
      summary: Exchange a code or refresh token for tokens
      tags:
      - OAuth
      description: Form-encoded per RFC 6749. authorization_code needs code, redirect_uri, client_id and code_verifier; refresh_token needs refresh_token and client_id. Refresh tokens rotate on every use; presenting a used one revokes the whole grant. Access tokens live one hour, refresh tokens thirty days. Confidential clients authenticate with HTTP Basic or client_secret in the form.
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                grant_type:
                  type: string
                  description: authorization_code or refresh_token.
                code:
                  type: string
                redirect_uri:
                  type: string
                client_id:
                  type: string
                client_secret:
                  type: string
                code_verifier:
                  type: string
                refresh_token:
                  type: string
                scope:
                  type: string
                  description: On refresh, may not widen the granted scopes. A narrower request is accepted, but the tokens keep the whole granted scope, and the response scope says so.
                resource:
                  type: string
      security: []
      responses:
        '200':
          description: Tokens. The access token is presented as a Bearer to the MCP endpoint.
          content:
            application/json:
              schema:
                description: Tokens. The access token is presented as a Bearer to the MCP endpoint.
                type: object
                properties:
                  access_token:
                    type: string
                  token_type:
                    type: string
                  expires_in:
                    type: integer
                  refresh_token:
                    type: string
                  scope:
                    type: string
        '400':
          description: invalid_request, invalid_grant, invalid_scope, invalid_target or unsupported_grant_type.
          content:
            application/json:
              schema:
                description: invalid_request, invalid_grant, invalid_scope, invalid_target or unsupported_grant_type.
                type: object
                properties:
                  error:
                    type: string
                  error_description:
                    type: string
        '401':
          description: invalid_client.
          content:
            application/json:
              schema:
                description: invalid_client.
                type: object
                properties:
                  error:
                    type: string
                  error_description:
                    type: string
        '429':
          description: 'slow_down: 60 requests a minute from one address.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
      operationId: postOauthToken
      x-operation-id-source: derived
  /oauth/register:
    post:
      summary: Register a client dynamically (RFC 7591)
      tags:
      - OAuth
      description: 'Public clients only: token_endpoint_auth_method must be none and no secret is issued. Prefer a Client ID Metadata Document, which needs no registration. redirect_uris must be https or loopback http. A registration that no user approves within two days is removed, and the client must register again.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                client_name:
                  type: string
                  description: Required. At most 100 characters.
                redirect_uris:
                  type: array
                  items:
                    type: string
                  description: Required, at least one; https or loopback http.
                token_endpoint_auth_method:
                  type: string
                  description: Only none is accepted here.
                grant_types:
                  type: array
                  items:
                    type: string
                response_types:
                  type: array
                  items:
                    type: string
                application_type:
                  type: string
                  description: web or native.
                client_uri:
                  type: string
                logo_uri:
                  type: string
      security: []
      responses:
        '201':
          description: The registered client.
          content:
            application/json:
              schema:
                description: The registered client.
                type: object
                properties:
                  client_id:
                    type: string
                  client_id_issued_at:
                    type: integer
                  client_name:
                    type: string
                  redirect_uris:
                    type: array
                    items:
                      type: string
                  token_endpoint_auth_method:
                    type: string
                  grant_types:
                    type: array
                    items:
                      type: string
                  response_types:
                    type: array
                    items:
                      type: string
        '400':
          description: invalid_redirect_uri or invalid_client_metadata.
          content:
            application/json:
              schema:
                description: invalid_redirect_uri or invalid_client_metadata.
                type: object
                properties:
                  error:
                    type: string
                  error_description:
                    type: string
        '429':
          description: 'slow_down: 10 registrations a minute from one address.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
        '503':
          description: 'temporarily_unavailable: too many registrations across all callers are waiting on a first approval, so new ones are paused. Retry later, or use a Client ID Metadata Document, which needs no registration.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
      operationId: postOauthRegister
      x-operation-id-source: derived
  /oauth/revoke:
    post:
      summary: Revoke a grant by one of its tokens (RFC 7009)
      tags:
      - OAuth
      description: Revokes the whole grant the access or refresh token belongs to, including the API key behind it. Answers 200 whether or not there was anything to revoke; only an Authorization header whose Basic credentials cannot be decoded gets 401 invalid_client.
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                token:
                  type: string
                  description: Required.
                token_type_hint:
                  type: string
                  description: access_token or refresh_token.
                client_id:
                  type: string
                client_secret:
                  type: string
      security: []
      responses:
        '200':
          description: Revoked, or nothing to revoke.
          content:
            application/json:
              schema:
                description: Revoked, or nothing to revoke.
                type: object
                properties: {}
        '401':
          description: 'invalid_client: the Basic credentials could not be decoded.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
        '429':
          description: 'slow_down: 30 requests a minute from one address.'
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthError'
      operationId: postOauthRevoke
      x-operation-id-source: derived
components:
  schemas:
    OAuthError:
      type: object
      additionalProperties: true
      required:
      - error
      properties:
        error:
          type: string
        error_description:
          type: string
      description: OAuth error body (RFC 6749 section 5.2), not the API's standard Error shape.
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: Use `mk_live_...` for production or `mk_test_...` for testing.
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'Alternative to the Authorization header: send `mk_live_...` or `mk_test_...` as X-API-Key directly.'