BuildWorkPro OAuth API

OAuth 2.1 authorization, token exchange and dynamic client registration.

Operations 6

GET /oauth/authorize OAuth 2.1 authorization endpoint (consent screen) #
POST /oauth/authorize OAuth 2.1 consent decision #
POST /oauth/token OAuth 2.1 token endpoint #
POST /oauth/revoke OAuth 2.0 Token Revocation (RFC 7009) #
GET /oauth/userinfo OAuth/OpenID userinfo endpoint #
POST /oauth/register Dynamic Client Registration (RFC 7591) #

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/buildworkpro-com:buildworkpro-com-oauth-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

buildworkpro-com-oauth-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: BuildWorkPro OAuth API
  version: 1.0.0
  description: Construction project management, CRM, and workflows — public REST API.
  contact:
    name: BuildWorkPro Developers
    email: developers@buildworkpro.com
  license:
    name: Proprietary
    url: https://buildworkpro.com/terms
servers:
- url: https://app.buildworkpro.com/api/v1
  description: Production
security:
- bearerAuth: []
tags:
- name: OAuth
  description: OAuth 2.1 authorization, token exchange and dynamic client registration.
paths:
  /oauth/authorize:
    get:
      summary: OAuth 2.1 authorization endpoint (consent screen)
      description: Renders an HTML consent screen. The user must be authenticated via the first-party session cookie. On approval the user is redirected to redirect_uri with `?code=&state=`. On error in the validation phase, fatal errors render an HTML error page (no redirect); validation errors after redirect_uri verification redirect with `?error=&state=`.
      security: []
      tags:
      - OAuth
      parameters:
      - schema:
          type: string
          enum:
          - code
        required: true
        name: response_type
        in: query
      - schema:
          type: string
        required: true
        name: client_id
        in: query
      - schema:
          type: string
          format: uri
        required: true
        name: redirect_uri
        in: query
      - schema:
          type: string
          minLength: 43
          maxLength: 128
        required: true
        name: code_challenge
        in: query
      - schema:
          type: string
          enum:
          - S256
        required: true
        name: code_challenge_method
        in: query
      - schema:
          type: string
        required: false
        name: scope
        in: query
      - schema:
          type: string
        required: false
        name: state
        in: query
      responses:
        '200':
          description: Consent screen rendered (HTML)
          content:
            text/html:
              schema:
                type: string
        '302':
          description: Redirect to client redirect_uri with code or error
        '400':
          description: Fatal validation error (HTML)
          content:
            text/html:
              schema:
                type: string
      operationId: getOauthAuthorize
      x-rate-limit-cost: 1
    post:
      summary: OAuth 2.1 consent decision
      description: Receives the user's Approve/Deny decision from the consent form. Body is form-encoded with `request_uri` (the original GET URL) and `decision` (approve or deny). Always redirects back to the client's redirect_uri.
      security: []
      tags:
      - OAuth
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                request_uri:
                  type: string
                decision:
                  type: string
                  enum:
                  - approve
                  - deny
              required:
              - request_uri
              - decision
      responses:
        '302':
          description: Redirect to client redirect_uri
        '400':
          description: Fatal validation error (HTML)
          content:
            text/html:
              schema:
                type: string
      operationId: postOauthAuthorize
      x-rate-limit-cost: 5
  /oauth/token:
    post:
      summary: OAuth 2.1 token endpoint
      description: 'Exchanges an authorization code (with PKCE verifier) or a refresh token for a new access token (and rotated refresh token). Body MUST be application/x-www-form-urlencoded per RFC 6749. Response carries Cache-Control: no-store. Confidential clients authenticate by passing client_secret in the body; public clients omit it. Refresh token reuse triggers family-wide revocation of all access + refresh tokens issued from the original grant.'
      security: []
      tags:
      - OAuth
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/OauthTokenRequest'
      responses:
        '200':
          description: Access token issued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthTokenResponse'
        '400':
          description: RFC 6749 §5.2 error envelope (invalid_request, invalid_grant, invalid_client, unsupported_grant_type)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthTokenError'
        '401':
          description: Client authentication failed (invalid_client)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthTokenError'
      operationId: postOauthToken
      x-rate-limit-cost: 5
  /oauth/revoke:
    post:
      summary: OAuth 2.0 Token Revocation (RFC 7009)
      description: Revokes an access token or refresh token. Body MUST be application/x-www-form-urlencoded. Per RFC 7009 §2.2, the response is 200 OK whether the token was successfully revoked, already revoked, expired, or unknown — this prevents leaking information about token validity. Revoking a refresh token cascades to the entire token family (all access + refresh tokens issued from the same grant). Revoking an access token does NOT cascade.
      security: []
      tags:
      - OAuth
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/OauthRevokeRequest'
      responses:
        '200':
          description: Token revoked, already revoked, expired, or unknown — all return 200 per RFC 7009 §2.2
        '400':
          description: RFC 7009 error envelope (invalid_request, invalid_client, invalid_grant)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthRevokeError'
        '401':
          description: Client authentication failed (invalid_client)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthRevokeError'
      operationId: postOauthRevoke
      x-rate-limit-cost: 5
  /oauth/userinfo:
    get:
      summary: OAuth/OpenID userinfo endpoint
      description: 'Returns identity information about the resource owner authenticated by the presented access token. Authentication is the standard `Authorization: Bearer` header — both API keys (bwp_live_/bwp_test_) and OAuth access tokens (bwp_at_) are accepted. No scope is required to call this endpoint.'
      security:
      - bearerAuth: []
      - oauth2: []
      tags:
      - OAuth
      responses:
        '200':
          description: Identity claims for the resource owner
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthUserinfo'
        '401':
          description: Authentication missing, invalid, expired, or membership revoked
          content:
            application/problem+json:
              schema:
                type: object
                properties: {}
      operationId: getOauthUserinfo
      x-rate-limit-cost: 1
  /oauth/register:
    post:
      summary: Dynamic Client Registration (RFC 7591)
      description: Self-registers a new OAuth client. Public endpoint — no authentication required. Per-IP rate-limited to 5 requests/minute. Each redirect_uri must be https, a loopback http URL on any port (http://127.0.0.1:{port}, http://localhost:{port}, http://[::1]:{port} — RFC 8252 §7.3), or a private-use scheme such as cursor:// (RFC 8252 §7.1); script-injection schemes (javascript:, data:, file:, blob:), embedded credentials, and fragments are rejected.
      security: []
      tags:
      - OAuth
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OauthClientRegistrationRequest'
      responses:
        '201':
          description: Client registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthClientRegistration'
        '400':
          description: RFC 7591 error envelope (invalid_client_metadata, invalid_redirect_uri, invalid_scope)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthRegistrationError'
        '429':
          description: Per-IP rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OauthRegistrationError'
      operationId: postOauthRegister
      x-rate-limit-cost: 5
components:
  schemas:
    OauthTokenRequest:
      type: object
      properties:
        grant_type:
          type: string
          description: 'OAuth 2.1 grant type. Supported: authorization_code, refresh_token.'
          example: authorization_code
        code:
          type: string
          description: Authorization code (required for grant_type=authorization_code).
        redirect_uri:
          type: string
          description: Must exact-match the redirect_uri originally used to obtain the code.
        client_id:
          type: string
          description: OAuth client identifier issued by the registration endpoint.
        client_secret:
          type: string
          description: Required for confidential clients; MUST be omitted for public clients.
        code_verifier:
          type: string
          description: PKCE verifier (S256). Required for grant_type=authorization_code.
        refresh_token:
          type: string
          description: Refresh token (required for grant_type=refresh_token).
        scope:
          type: string
          description: Optional space-separated scope list. For grant_type=refresh_token, MUST be a subset of the original refresh token's scopes (scope downgrade only). Upgrade is rejected with invalid_scope.
      required:
      - grant_type
      - client_id
    OauthUserinfo:
      type: object
      properties:
        sub:
          type: string
          description: Stringified user id of the resource owner.
          example: '42'
        tenant_id:
          type: integer
          description: Tenant the access token is scoped to.
          example: 7
        email:
          type: string
          format: email
          description: Email address of the resource owner.
          example: jane@example.com
        name:
          type: string
          description: '`firstName lastName`, trimmed. Empty string when both names are missing — never null.'
          example: Jane Doe
        role:
          type: string
          description: The user's tenant role at the moment the request was authenticated.
          example: company_admin
        scopes:
          type: array
          items:
            type: string
          description: The scopes carried by the presented access token.
          example:
          - contacts:read
          - leads:read
      required:
      - sub
      - tenant_id
      - email
      - name
      - role
      - scopes
    OauthRevokeError:
      type: object
      properties:
        error:
          type: string
        error_description:
          type: string
      required:
      - error
    OauthRevokeRequest:
      type: object
      properties:
        token:
          type: string
          description: The token to revoke. Can be either an access token (prefix bwp_at_) or a refresh token (prefix bwp_rt_).
        token_type_hint:
          type: string
          enum:
          - access_token
          - refresh_token
          description: Optional hint about the token type. The server still falls back to the other type if the hinted lookup misses (RFC 7009 §4.1.2).
        client_id:
          type: string
          description: OAuth client identifier issued by the registration endpoint.
        client_secret:
          type: string
          description: Required for confidential clients; MUST be omitted for public clients.
      required:
      - token
      - client_id
    OauthClientRegistration:
      type: object
      properties:
        client_id:
          type: string
        client_secret:
          type: string
        client_id_issued_at:
          type: integer
        client_name:
          type: string
        client_secret_expires_at:
          type: integer
        redirect_uris:
          type: array
          items:
            type: string
            format: uri
        grant_types:
          type: array
          items:
            type: string
        scope:
          type: string
        token_endpoint_auth_method:
          type: string
          enum:
          - none
          - client_secret_basic
          - client_secret_post
      required:
      - client_id
      - client_id_issued_at
      - client_name
      - redirect_uris
      - grant_types
      - scope
      - token_endpoint_auth_method
    OauthRegistrationError:
      type: object
      properties:
        error:
          type: string
        error_description:
          type: string
      required:
      - error
    OauthClientRegistrationRequest:
      type: object
      properties:
        client_name:
          type: string
          minLength: 1
          maxLength: 200
        redirect_uris:
          type: array
          items:
            type: string
            format: uri
          minItems: 1
          maxItems: 10
        grant_types:
          type: array
          items:
            type: string
            enum:
            - authorization_code
            - refresh_token
          default:
          - authorization_code
          - refresh_token
        scope:
          type: string
          default: ''
        token_endpoint_auth_method:
          type: string
          enum:
          - none
          - client_secret_basic
          - client_secret_post
          default: none
        contact:
          type: string
          format: email
      required:
      - client_name
      - redirect_uris
    OauthTokenResponse:
      type: object
      properties:
        access_token:
          type: string
        token_type:
          type: string
          enum:
          - Bearer
        expires_in:
          type: integer
        refresh_token:
          type: string
        scope:
          type: string
      required:
      - access_token
      - token_type
      - expires_in
      - scope
    OauthTokenError:
      type: object
      properties:
        error:
          type: string
        error_description:
          type: string
      required:
      - error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: bwp_live_... or bwp_test_...
      description: Long-lived tenant-wide API key. Provision in Settings → Developer → API Keys.
    oauth2:
      type: oauth2
      description: OAuth 2.1 per-user token. Available in Phase 4.
      flows:
        authorizationCode:
          authorizationUrl: https://app.buildworkpro.com/api/v1/oauth/authorize
          tokenUrl: https://app.buildworkpro.com/api/v1/oauth/token
          refreshUrl: https://app.buildworkpro.com/api/v1/oauth/token
          scopes: {}