Assinafy OAuth API

The token, revocation and userinfo endpoints an OAuth application calls, and this API's protected-resource metadata. New to OAuth with Assinafy? Read **OAuth Integration Guide** first. The authorization server's own metadata is served at `https://auth.assinafy.com.br/.well-known/oauth-authorization-server`, not on this API: read endpoint URLs from it instead of hardcoding them.

Operations 4

POST /v1/oauth/token Exchange a code, refresh token, or subject token for an access token #
POST /v1/oauth/revoke Revoke a token #
GET /v1/oauth/userinfo OpenID Connect userinfo #
GET /.well-known/oauth-protected-resource OAuth 2.0 protected resource metadata #

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/assinafy-com-br:assinafy-com-br-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

assinafy-com-br-oauth-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Assinafy Com Br OAuth API
  version: 1.0.0
  description: 'Operations tagged OAuth across 2 of this provider''s published API definitions: assinafy-com-br-openapi.json, assinafy-com-br-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.assinafy.com.br
  description: Production
- url: https://sandbox.assinafy.com.br
  description: Sandbox
tags:
- name: OAuth
  description: 'The token, revocation and userinfo endpoints an OAuth application calls, and this API''s protected-resource metadata. New to OAuth with Assinafy? Read **OAuth Integration Guide** first. The authorization server''s own metadata is served at `https://auth.assinafy.com.br/.well-known/oauth-authorization-server`, not on this API: read endpoint URLs from it instead of hardcoding them.'
paths:
  /v1/oauth/token:
    post:
      tags:
      - OAuth
      summary: Exchange a code, refresh token, or subject token for an access token
      description: 'Implements the RFC 6749 §5.1/§5.2 token-endpoint body contract in

        * both directions: a successful exchange returns a flat JSON object with

        * `access_token` at the top level, and a failure returns a flat

        * `{error, error_description}` object — neither is wrapped in this API''s

        * usual response envelope, since no standard OAuth client library (or MCP

        * connector) would find `access_token` or `error` inside a `data` key.

        *

        * The third grant, `urn:ietf:params:oauth:grant-type:token-exchange` (RFC 8693),

        * is restricted to a confidential internal-service client (see `/oauth/introspect`)

        * and trades a front-end resource''s access token (the `subject_token`) for one

        * minted for THIS API — the crossing an MCP server makes after a user consents,

        * since its own token can never be forwarded here directly. The issued token is

        * never wider than the subject: `scope`, when sent, must be a subset of the

        * subject''s own scopes, and `resource` must equal this API''s own resource

        * identifier exactly. No refresh token is issued; the caller re-exchanges from

        * the user''s own token instead of holding unattended API access.


        Copy as Markdown Open in ChatGPT Open in Claude'
      operationId: b214b71efe5b11ac52d79597108ab2ba
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/OAuthTokenRequest'
          application/json:
            schema:
              $ref: '#/components/schemas/OAuthTokenRequest'
      responses:
        '200':
          description: The token response
          content:
            application/json:
              schema:
                properties:
                  access_token:
                    type: string
                  issued_token_type:
                    description: Present only for the token-exchange grant, per RFC 8693 §2.2.1.
                    type: string
                    example: urn:ietf:params:oauth:token-type:access_token
                  token_type:
                    type: string
                    example: Bearer
                  expires_in:
                    description: For the token-exchange grant, clamped to the subject token's own remaining lifetime as well as the exchanged-token TTL — never longer than either.
                    type: integer
                    example: 3600
                  refresh_token:
                    description: Present only when the `offline_access` scope was requested AND consented on the authorization_code/refresh_token grants. Never present for the token-exchange grant. Without it a client must send the user through the authorization flow again once the access token expires.
                    type:
                    - string
                    - 'null'
                  scope:
                    description: The scope of the ACCESS token. `offline_access` is a request-time signal rather than a permission, so it never appears here even when it was requested.
                    type: string
                    example: documents:read
                  id_token:
                    description: A signed OIDC id_token (RS256). Present only when the openid scope was granted.
                    type:
                    - string
                    - 'null'
                type: object
        '400':
          description: '`invalid_grant` (bad, expired, replayed, or wrong-client authorization code; a `code_verifier` outside the RFC 7636 grammar of 43-128 unreserved characters; redirect_uri mismatch; a refresh token whose authorization no longer includes `offline_access`; for token-exchange, a `subject_token` that is unusable, itself an exchanged token, not visible to service clients, or expired), `invalid_target` (a `resource` this server does not issue tokens for, one disagreeing with the authorized value, or — for token-exchange — one other than this API''s own resource identifier), `invalid_scope` (token-exchange only: the requested `scope` is not a subset of the subject token''s own scopes), `invalid_request` (token-exchange only: an unsupported `subject_token_type`/`requested_token_type`), or `unsupported_grant_type`'
          content:
            application/json:
              schema:
                properties:
                  error:
                    type: string
                    enum:
                    - invalid_grant
                    - invalid_target
                    - invalid_scope
                    - invalid_request
                    - unsupported_grant_type
                  error_description:
                    type: string
                type: object
        '401':
          description: '`invalid_client` — unknown/disabled client or failed client authentication. The description never reveals whether client_id exists.'
          content:
            application/json:
              schema:
                properties:
                  error:
                    type: string
                    example: invalid_client
                  error_description:
                    type: string
                    example: Client authentication failed.
                type: object
        '429':
          description: Rate limit exceeded; wait the `Retry-After` seconds. Limited per caller IP.
        '500':
          $ref: '#/components/responses/ServerError'
      security: []
    servers:
    - url: https://api.assinafy.com.br
      description: Production
    - url: https://sandbox.assinafy.com.br
      description: Sandbox
  /v1/oauth/revoke:
    post:
      tags:
      - OAuth
      summary: Revoke a token
      description: 'Revokes an access or refresh token. Every token outcome always returns 200 — including a token that does not exist, is already revoked, or is malformed — so the endpoint can never be used to probe whether a token exists. The one exception is failed client authentication, which returns 401.


        Copy as Markdown Open in ChatGPT Open in Claude'
      operationId: 4da9798b52b228fa0be9ddc534b42eee
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/OAuthRevokeRequest'
          application/json:
            schema:
              $ref: '#/components/schemas/OAuthRevokeRequest'
      responses:
        '200':
          description: Revoked
        '401':
          description: '`invalid_client` — the only case that is not reported as success. Every token outcome (revoked, already revoked, unknown, malformed) always returns 200; only failed client authentication returns 401.'
          content:
            application/json:
              schema:
                properties:
                  error:
                    type: string
                    example: invalid_client
                  error_description:
                    type: string
                    example: Client authentication failed.
                type: object
        '500':
          $ref: '#/components/responses/ServerError'
      security: []
    servers:
    - url: https://api.assinafy.com.br
      description: Production
    - url: https://sandbox.assinafy.com.br
      description: Sandbox
  /v1/oauth/userinfo:
    get:
      tags:
      - OAuth
      summary: OpenID Connect userinfo
      description: 'Claims about the user who authorized this token. Requires the openid scope; name requires profile and email requires email. Per OIDC Core §5.3.2, the response is a flat JSON object of claims — never this API''s usual `{status, data, message}` envelope.


        Copy as Markdown Open in ChatGPT Open in Claude'
      operationId: b920740c01ff33773b9e6c13be139f7f
      responses:
        '200':
          description: The user's claims
          content:
            application/json:
              schema:
                properties:
                  sub:
                    type: string
                    example: d6zqpbyog2v3xvxerwn8la94
                  name:
                    type:
                    - string
                    - 'null'
                    example: Maria Silva
                  email:
                    type:
                    - string
                    - 'null'
                    format: email
                  email_verified:
                    type:
                    - boolean
                    - 'null'
                type: object
        '403':
          $ref: '#/components/responses/Forbidden'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/ServerError'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
    servers:
    - url: https://api.assinafy.com.br
      description: Production
    - url: https://sandbox.assinafy.com.br
      description: Sandbox
  /.well-known/oauth-protected-resource:
    get:
      tags:
      - OAuth
      summary: OAuth 2.0 protected resource metadata
      description: 'RFC 9728. Identifies this API as a protected resource, the

        * authorization server(s) that can issue tokens for it, and the scopes it

        * accepts. `scopes_supported` deliberately excludes `offline_access` — per the

        * MCP specification, requesting a refresh token is a client concern, not

        * something a resource is protected by. Also referenced from the

        * `WWW-Authenticate: Bearer resource_metadata="..."` challenge on a 401/403.

        * Per RFC 8615, the response is the bare metadata object itself — never this

        * API''s usual `{status, data, message}` envelope. The `authorization_servers` entry names the host that owns the browser-facing flow — start every integration by fetching `{authorization_servers[0]}/.well-known/oauth-authorization-server` (RFC 8414) from there, not from this API.


        Copy as Markdown Open in ChatGPT Open in Claude'
      operationId: 94f8ad95c46aea75be0241484f573ed6
      responses:
        '200':
          description: The protected resource metadata
          content:
            application/json:
              schema:
                properties:
                  resource:
                    type: string
                    format: uri
                  authorization_servers:
                    type: array
                    items:
                      type: string
                      format: uri
                  scopes_supported:
                    type: array
                    items:
                      type: string
                  bearer_methods_supported:
                    type: array
                    items:
                      type: string
                      example: header
                type: object
        '500':
          $ref: '#/components/responses/ServerError'
      security: []
    servers:
    - url: https://api.assinafy.com.br
      description: Production
    - url: https://sandbox.assinafy.com.br
      description: Sandbox
components:
  schemas:
    OAuthTokenRequest:
      description: Body of `POST /v1/oauth/token`. Sent form-encoded per RFC 6749, or as JSON.
      required:
      - grant_type
      - client_id
      properties:
        grant_type:
          description: '`urn:ietf:params:oauth:grant-type:token-exchange` is for internal service clients only (Assinafy''s own MCP server) — an ordinary confidential or public client authenticates with it and always gets `invalid_client`, exactly as an unrecognized client would. Everyday integrators use `authorization_code` and `refresh_token`.'
          type: string
          enum:
          - authorization_code
          - refresh_token
          - urn:ietf:params:oauth:grant-type:token-exchange
        code:
          type: string
        redirect_uri:
          type: string
          format: uri
        code_verifier:
          description: 'RFC 7636: 43-128 characters from [A-Za-z0-9-._~]. Shorter values are rejected with `invalid_grant`.'
          type: string
        refresh_token:
          type: string
        client_id:
          type: string
        client_secret:
          description: Confidential clients only. Public clients authenticate with PKCE and are never issued a secret; the token-exchange grant requires a confidential, internal-service client and therefore always requires this.
          type: string
        resource:
          description: RFC 8707 resource indicator. For `authorization_code`/`refresh_token`, optional; when present it must be the `resource` value published by /.well-known/oauth-protected-resource and must match the one sent to /authorize, otherwise `invalid_target`. For the token-exchange grant it is REQUIRED and must equal this API's own resource identifier exactly (never a front-end resource such as the MCP server), otherwise `invalid_target`.
          type: string
          format: uri
        subject_token:
          description: Token-exchange grant only. The front-end resource's access token being traded in. Must be a live, original (never itself exchanged) token minted for a resource this server issues tokens for, other than this API's own audience.
          type: string
        subject_token_type:
          description: Token-exchange grant only. Required; only `urn:ietf:params:oauth:token-type:access_token` is supported.
          type: string
          enum:
          - urn:ietf:params:oauth:token-type:access_token
        requested_token_type:
          description: Token-exchange grant only. Optional; when present it must agree with the only type this server issues.
          type: string
          enum:
          - urn:ietf:params:oauth:token-type:access_token
      type: object
    OAuthRevokeRequest:
      description: Body of `POST /v1/oauth/revoke`. Sent form-encoded per RFC 7009, or as JSON.
      required:
      - token
      - client_id
      properties:
        token:
          type: string
        token_type_hint:
          type: string
          enum:
          - access_token
          - refresh_token
        client_id:
          type: string
        client_secret:
          type: string
      type: object
    ErrorEnvelope:
      description: Standard error wrapper. `status` mirrors the HTTP status code.
      properties:
        status:
          type: integer
          example: 400
        message:
          description: Human-readable error message.
          type: string
          example: Bad request.
        data:
          type:
          - object
          - 'null'
          example: null
      type: object
  responses:
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            type: object
            allOf:
            - $ref: '#/components/schemas/ErrorEnvelope'
            - properties:
                status:
                  type: integer
                  example: 401
                message:
                  type: string
                  example: Your request was made with invalid credentials.
              type: object
    Forbidden:
      description: Authenticated but not allowed to perform this action.
      content:
        application/json:
          schema:
            type: object
            allOf:
            - $ref: '#/components/schemas/ErrorEnvelope'
            - properties:
                status:
                  type: integer
                  example: 403
                message:
                  type: string
                  example: You are not allowed to perform this action.
              type: object
    ServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            type: object
            allOf:
            - $ref: '#/components/schemas/ErrorEnvelope'
            - properties:
                status:
                  type: integer
                  example: 500
                message:
                  type: string
                  example: An unexpected error occurred.
              type: object
  securitySchemes:
    bearerAuth:
      type: http
      description: 'Access token: `Authorization: Bearer {access_token}`.'
      bearerFormat: JWT
      scheme: bearer
    apiKeyAuth:
      type: apiKey
      description: Permanent API key (recommended for back-end integrations).
      name: X-Api-Key
      in: header
    signerAccessCode:
      type: apiKey
      description: 'Signer access code used by signer-facing (Signing) endpoints instead of a user token: the code in the signer''s signing link, sent as the `signer-access-code` query or body parameter. It can be used again and has no expiry; it stops working when the signing request is removed. Treat it as a secret.'
      name: signer-access-code
      in: query
    oauth2:
      type: oauth2
      description: 'OAuth 2.1 authorization code flow with mandatory PKCE (S256), for applications and AI assistants acting in a user''s workspace with that user''s permission — as opposed to `apiKeyAuth`/`bearerAuth`, which authenticate the workspace or user directly. A token carries only the scopes the user approved and works for one workspace. Endpoints are published by the authorization server at `https://auth.assinafy.com.br/.well-known/oauth-authorization-server`. An OAuth token cannot reach billing, account lifecycle, credential management or admin surfaces regardless of scope. A missing scope answers `403` with `WWW-Authenticate: Bearer error="insufficient_scope"` naming it. See **OAuth Integration Guide** for the full flow.'
      flows:
        authorizationCode:
          authorizationUrl: https://auth.assinafy.com.br/oauth/authorize
          tokenUrl: https://api.assinafy.com.br/v1/oauth/token
          refreshUrl: https://api.assinafy.com.br/v1/oauth/token
          scopes:
            documents:read: Read documents, their pages, tags, signers, assignments and activity, and the WhatsApp notifications sent for an assignment.
            documents:write: Create, update and delete documents, and manage their signers, assignments and activity.
            templates:read: Read reusable document templates, their pages, roles, fields and tags.
            templates:write: Create, update and delete templates, their pages, roles, fields and tags.
            account:read: Read the workspace's profile, theme and logo.
            webhooks:write: Change the workspace's webhook subscription (delivery URL, events, contact email), deactivate it, manage webhook endpoints and re-send a delivery.
            openid: Identify the authenticated user (OpenID Connect `sub` claim) and enable the `/v1/oauth/userinfo` endpoint.
            profile: Include the user's name in the `id_token`/userinfo claims.
            email: Include the user's email and its verification status in the `id_token`/userinfo claims.
            offline_access: Request a refresh token, so the app keeps working after the user's session expires without prompting them again. Only granted to a client that explicitly asks for it.
x-refined-from:
- assinafy-com-br-openapi.json
- assinafy-com-br-openapi.json