openapi: 3.1.0
info:
  title: Memo Bank Marketplace
  description: "The Memo Bank Marketplace allows third-party developers to build integrations\
    \ for Memo Bank customers. \n\nMarketplace applications use the same API as our\
    \ customers, with an OAuth2 layer on top to access resources on their behalf.\n\
    \nThis documentation only covers the marketplace-specific concerns. For the remaining\
    \ API reference, see the [Memo Bank API documentation](https://docs.api.memo.bank).\n"
  version: "1.0"
servers:
- url: https://api.memo.bank
  description: Production
- url: https://api.sandbox.memo.bank
  description: Sandbox
tags:
- name: OAuth2
  description: |
    OAuth2 token management endpoints.
paths:
  /oauth2/token:
    post:
      tags:
      - OAuth2
      summary: Create an access token
      operationId: createToken
      requestBody:
        content:
          application/json:
            schema:
              type: object
              discriminator:
                propertyName: grant_type
                mapping:
                  authorization_code: "#/components/schemas/AuthorizationCodeGrant"
                  refresh_token: "#/components/schemas/RefreshTokenGrant"
              oneOf:
              - $ref: "#/components/schemas/AuthorizationCodeGrant"
              - $ref: "#/components/schemas/RefreshTokenGrant"
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OAuth2Token"
      security:
      - JWT: []
components:
  schemas:
    OAuth2Token:
      required:
      - access_token
      - connection_id
      - expires_in
      - refresh_token
      - scope
      - token_type
      type: object
      properties:
        access_token:
          type: string
          description: The access token.
        token_type:
          type: string
          description: The token type.
          example: bearer
        expires_in:
          type: integer
          description: The lifetime of the access token in seconds.
          format: int64
          example: 3600
        refresh_token:
          type: string
          description: The refresh token.
        scope:
          type: string
          description: Space-separated list of granted scopes.
        connection_id:
          type: string
          description: ID of the connection this token is linked to.
          format: uuid
    AuthorizationCodeGrant:
      required:
      - client_id
      - client_secret
      - code
      - redirect_uri
      type: object
      allOf:
      - $ref: "#/components/schemas/CreateOauth2TokenDTODiscriminator"
      - type: object
        properties:
          code:
            type: string
            description: Authorization code received from the authorization endpoint.
          redirect_uri:
            type: string
            description: Redirect URI used in the authorization request.
          client_id:
            type: string
            description: OAuth2 client identifier.
          client_secret:
            type: string
            description: OAuth2 client secret.
    CreateOauth2TokenDTO:
      type: object
      discriminator:
        propertyName: grant_type
        mapping:
          authorization_code: "#/components/schemas/AuthorizationCodeGrant"
          refresh_token: "#/components/schemas/RefreshTokenGrant"
      oneOf:
      - $ref: "#/components/schemas/AuthorizationCodeGrant"
      - $ref: "#/components/schemas/RefreshTokenGrant"
    RefreshTokenGrant:
      required:
      - client_id
      - client_secret
      - refresh_token
      type: object
      allOf:
      - $ref: "#/components/schemas/CreateOauth2TokenDTODiscriminator"
      - type: object
        properties:
          refresh_token:
            type: string
            description: Refresh token received from a previous token request.
          client_id:
            type: string
            description: OAuth2 client identifier.
          client_secret:
            type: string
            description: OAuth2 client secret.
          scope:
            type: string
            description: Space-separated list of scopes. Must be a subset of original
              scopes.
    CreateOauth2TokenDTODiscriminator:
      required:
      - grant_type
      type: object
      properties:
        grant_type:
          type: string
x-topics:
- title: Getting started
  content: |
    [Contact us](mailto:openbanking@memo.bank) to apply for a marketplace application registration.

    To register, you'll need:
    - A **private key** to sign the JWT to authenticate your requests;
    - A set of **scopes** your application will have access to;
    - One or more **redirect URIs** to be used during the OAuth2 flow.


    Upon registration, you'll receive the following pieces of information:
    - A **certificate** and its SHA256 thumbprint to identify your application;
    - A **secret code** to include in the JWT to authenticate your requests;
    - A **client ID** to identify your application when using the OAuth2 flow;
    - A **client secret** to authenticate your OAuth2 token requests;
    - A **token** to authenticate our requests to your webhook.

    Keep your secrets secure and never expose them in client-side code.
- title: Authorization flow
  content: "Marketplace applications make use of the standard OAuth2 Authorization\
    \ Code flow:\n\n**1. Redirect the user to the authorization page**\n\nRedirect\
    \ the user's browser to `https://client.memo.bank/authorize` with the following\
    \ query parameters:\n- `client_id` — your application's client ID;\n- `redirect_uri`\
    \ — one of your registered redirect URIs;\n- `scope` — space-separated list of\
    \ requested scopes;\n- `state` — an opaque value to maintain state between the\
    \ request and callback.\n\n**2. User approves access**\n\nThe user reviews the\
    \ requested permissions and approves. They are then redirected to your `redirect_uri`\
    \ with a `code` in the query parameters.\n\nIf the user denies the access or if\
    \ an error occurs, they are redirected to your `redirect_uri` with an `error`\
    \ and optionally an `error_description` in the query parameters. \n\n**3. Exchange\
    \ the code with a token**\n\nMake a `POST` request to `/oauth2/token` using the\
    \ `authorization_code` grant type, along with the `code` you received during the\
    \ previous step, as well as your `redirect_uri`, `client_id` and `client_secret`.\n\
    \nSee the API reference for the [OAuth2 token endpoint](#operation-createtoken)\
    \ below for more details.\n\n**4. Refresh your access tokens**\n\nUse the `refresh_token`\
    \ grant type to obtain new access and refresh tokens without requiring the user\
    \ to re-authorize your  application.\n\n**Token lifetimes:**\n- Access token:\
    \ **2 hours**.\n- Refresh token: **14 days** (single use).\n- Authorization code:\
    \ **5 minutes** (single use).\n"
- title: Connection lifecycle
  content: |
    A connection represents the link between your application and a user on a specific Memo Bank workspace. A single connection can exist for a user/workspace pair at a given time.

    The ID of the connection can be retrieved from the [OAuth2 token endpoint](#operation-createtoken) and will be sent along events to the application's webhooks.

    When a user deactivates a connection, requests to the API will fail with an `inactive_connection` error code.
- title: Authentication
  content: |
    Marketplace applications authenticate themselves using the same JWT scheme as described in the [Memo Bank API documentation](https://docs.api.memo.bank/#doc-authentication). The only difference being that the JWT must be sent in the `X-Memo-Signature` header, while the `Authorization` header must be used to send the OAuth2 access token.

    In addition to the standard JWT claims, the JWT payload must include an `oat#S256` claim containing the base64url-encoded SHA-256 hash of the OAuth2 access token (`base64url(sha256(access_token))`, see [`base64url`](https://datatracker.ietf.org/doc/html/rfc7515#appendix-C)), This binds the signature to the specific access token used in the request.

    Your application can only access resources that fall within the granted scopes and the specific accounts the user has authorized. Attempting to access resources outside of scope will result in an error.

    For the full list of available API endpoints and their required scopes, please refer to the [Memo Bank API documentation](https://docs.api.memo.bank).
- title: Webhooks
  content: |
    Marketplace applications can receive webhook events when something happens on a connected user's workspace. The setup and configuration of webhooks, event types, payload format, delivery behavior and retry policy are the same as described in the [Memo Bank API documentation](https://docs.api.memo.bank/group/webhook-webhook).

    When sending an event to a marketplace application, we'll include a **`X-Memo-Connection-Id`** header. This header identifies which connection is linked to the event, allowing your application to route events to the correct context.

    When using the [Webhooks endpoints](https://docs.api.memo.bank/group/endpoint-webhooks), managed webhooks will be tied to the connection linked to the OAuth2 access token when making the call. This allows you to configure a  different URL for each connection. We can also configure a global  webhook tied to your application if you only need one URL or do not want to use these endpoints.
