openapi: 3.1.0
info:
  title: Bango Identity Verification API
  version: 1.0.{build_number}
  contact:
    name: Bango Support
    url: https://developer.bango.com
    email: support@bango.com
servers:
  - url: https://some-prod-tbd.bango.com
    description: Production server
tags:
  - name: env-production
    description: Currently deployed to prod env
  - name: plan-later
    description: Not yet planned
paths:
  /ns/{nsid}/identity/verifications:
    post:
      operationId: identity-verification-create
      summary: Create an identity verification session
      description: |
        Use this endpoint to create an identity verification session. API consumers use this session to authenticate/verify the end user and obtain a Payment Instrument Token for them.

        Include the `action` property to send an action immediately after the session is created.

        400 response error codes:
          - `invalid-json` if the request body isn't valid JSON format
          - `missing-parameter` for any mandatory parameter missing from the request body
          - `invalid-parameter` for any parameter that's syntactically or semantically incorrect. For example:
            - If this specification defines a parameter as a string, and an array of strings is supplied
            - If this specification defines a parameter as a datetime, and an invalid datetime is supplied
            - If parameters should be in a particular order (eg chronological datetimes) and they aren't
      tags:
        - env-production
      parameters:
        - $ref: '#/components/parameters/NamespaceId'
      requestBody:
        description: |
          Data needed to create an identity verification session.

          Partners can optionally include an `action` property. If present, the Bango Platform processes the action immediately after a successful session creation.
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                partnerSessionId:
                  $ref: '#/components/schemas/partnerSessionId'
                private:
                  $ref: '#/components/schemas/private'
                shared:
                  title: Data shared betweeen merchant and payment provider
                  description: |
                    Initial details of the negotiation between the merchant partner and the payment provider, from the merchant partner's perspective
                  type: object
                  properties:
                    nextAction:
                      $ref: '#/components/schemas/nextAction'
                    merchantToPaymentProvider:
                      $ref: '#/components/schemas/merchantToPaymentProvider'
                action:
                  $ref: '#/components/schemas/action'
      responses:
        '201':
          description: |
            Resource created.
          content:
            application/vnd.bango.identity.verification.v1+json:
              schema:
                $ref: '#/components/schemas/session'
        '400':
          $ref: '#/components/responses/BadRequestErrorResponse'
        '401':
          $ref: '#/components/responses/InvalidCredentialsErrorResponse'
        '403':
          $ref: '#/components/responses/PermissionDeniedErrorResponse'
        '404':
          $ref: '#/components/responses/NotFoundErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsErrorResponse'
        '500':
          description: Unexpected internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      oneOf:
                        - $ref: '#/components/schemas/internal-server-error'
                        - $ref: '#/components/schemas/payment-provider-failure'
                required:
                  - errors
        '503':
          $ref: '#/components/responses/ServiceUnavailableErrorResponse'
  /ns/{nsid}/identity/verifications/{ridOrAlias}:
    get:
      operationId: identity-verification-get
      summary: Retrieve an identity verification session
      description: |
        Use this endpoint to retrieve an identity verification session. The `flow` property of the session describes the selected identity verification flow, if any. The `state` property describes the current state of the session, and this may change over time. Partners can poll a session regularly to track asynchronous processes managed by the Bango Platform, such as sending messages to an end user's device through a payment provider's SMS service.

        To poll, partners can:
        - Use the `rid` of the session: this is a unique identifier (UUID v4) created by the Bango Platform
        - Use an alias for the `rid`, for example `partnerSessionId:fhie857jfskgiei`. (The Bango Platform creates this alias automatically if the partner specifies a `partnerSessionId` when creating the session)
      tags:
        - env-production
      parameters:
        - $ref: '#/components/parameters/NamespaceId'
        - $ref: '#/components/parameters/ResourceIdOrAlias'
      responses:
        '200':
          description: Resource found
          content:
            application/vnd.bango.identity.verification.v1+json:
              schema:
                $ref: '#/components/schemas/session'
        '401':
          $ref: '#/components/responses/InvalidCredentialsErrorResponse'
        '403':
          $ref: '#/components/responses/PermissionDeniedErrorResponse'
        '404':
          $ref: '#/components/responses/NotFoundErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsErrorResponse'
        '500':
          $ref: '#/components/responses/InternalServerErrorResponse'
        '503':
          $ref: '#/components/responses/ServiceUnavailableErrorResponse'
  /ns/{nsid}/identity/verifications/{rid}/actions:
    post:
      operationId: identity-verification-send-action
      summary: Update an identity verification session
      description: |
        Use this endpoint to update an identity verification session and/or to trigger tasks related to an identity verification session.

        API consumers request updates by sending _actions_ to this endpoint. An action specifies what you want to do to the resource. The Bango Platform decides whether the action is permitted, and if so it performs the action. An action might result in a change to the resource's properties, and might cause a side effect. Actions are logged as `*_REQUESTED` events (you can fetch events for a resource using a separate endpoint). The Bango Platform also logs events recording whether the action succeeded or failed.

        400 response error codes:
          - `invalid-json` if the request body isn't valid JSON format
          - `missing-parameter` if `type` is not present in the request body
          - `invalid-parameter` if `type` is not a valid action type
          - `missing-parameter` if `payload` is required and not present
          - `invalid-parameter` if `payload` is not the expected shape for the type of action (which may mean that `payload` is missing required parameters or some parameters are invalid: check the documentation to find out the expected payload shape for each action type)
      tags:
        - env-production
      parameters:
        - $ref: '#/components/parameters/NamespaceId'
        - $ref: '#/components/parameters/ResourceId'
      requestBody:
        description: |
          A request to update an identity verification session and trigger session-related tasks. A request specifies an action `type` and any action-specific data (the `payload`).

          Available action types:
          - `START_TRUSTED_FLOW`: A request to obtain a payment instrument token using the Trusted flow.
          - `START_NEGOTIATED_FLOW`: A request to obtain a payment instrument token using the Negotiated flow.
          - `START_MO_FLOW`: A request to obtain a payment instrument token using the MO flow.
          - `START_MT_FLOW`: A request to obtain a payment instrument token using the MT flow.
          - `VERIFY_OTP`: A request to check an end user's candidate OTP against the expected OTP.
          - `RESEND_OTP`: A request to resend the current OTP.
          - `RESET_OTP`: A request to resend/reset the OTP.
          - `CONFIRM_SESSION_IDENTITY`: Confirm that an end user was properly identified.
          - `REJECT_SESSION_IDENTITY`: Reject a tentative end user identification.
          - `UPDATE_SESSION_DATA`: A request to update private or shared data related to the identity verification session.

          Whether an action has any effect depends on the current `flow` and `state` properties of the session, and other factors. The response to this request is the session resource: the `flow` and `state` properties might have changed as a result of the request.
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/START_TRUSTED_FLOW'
                - $ref: '#/components/schemas/START_NEGOTIATED_FLOW'
                - $ref: '#/components/schemas/START_MO_FLOW'
                - $ref: '#/components/schemas/START_MT_FLOW'
                - $ref: '#/components/schemas/VERIFY_OTP'
                - $ref: '#/components/schemas/RESEND_OTP'
                - $ref: '#/components/schemas/RESET_OTP'
                - $ref: '#/components/schemas/CONFIRM_SESSION_IDENTITY'
                - $ref: '#/components/schemas/REJECT_SESSION_IDENTITY'
                - $ref: '#/components/schemas/UPDATE_SESSION_DATA'
                - $ref: '#/components/schemas/CANCEL_SESSION'
      responses:
        '200':
          description: |
            The updated resource.
          content:
            application/vnd.bango.identity.verification.v1+json:
              schema:
                $ref: '#/components/schemas/session'
        '400':
          $ref: '#/components/responses/BadRequestErrorResponse'
        '401':
          $ref: '#/components/responses/InvalidCredentialsErrorResponse'
        '403':
          $ref: '#/components/responses/PermissionDeniedErrorResponse'
        '404':
          $ref: '#/components/responses/NotFoundErrorResponse'
        '409':
          $ref: '#/components/responses/ConflictErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequestsErrorResponse'
        '500':
          description: Unexpected internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      oneOf:
                        - $ref: '#/components/schemas/internal-server-error'
                        - $ref: '#/components/schemas/payment-provider-failure'
                required:
                  - errors
        '503':
          $ref: '#/components/responses/ServiceUnavailableErrorResponse'
components:
  schemas:
    namespace-id:
      title: Namespace ID
      description: |
        Globally unique namespace ID. These IDs are opaque, not guessable, and not sequential.

        Bango provides each Bango partner with a unique set of resource URIs. All resource URI paths start with `/ns/{nsid}`, where `{nsid}` is the namespace ID. No other Bango partner shares this namespace. Partner credentials permit access only to URIs with this namespace.
      type: string
      format: uuid
      example: 673c74de-ce5b-4f79-9851-2544d1d836cb
    partnerSessionId:
      description: |
        A session ID supplied by the partner. This is assumed to be unique across all the partner's identity verification sessions.
      type: string
      minLength: 1
      example: e9342a9f-ff3f-44ad-8e30-8a6f9a820060
    private:
      description: |
        A place for the merchant partner to store private data related to the identity verification session. Once the payment instrument token is generated, this data is associated with the token.

        Merchant partners can initialize the data when creating a session, and can patch this data later when starting a flow or using an UPDATE_SESSION_DATA action.

        Supports any data (constraints TBD). This schema defines some commonly used properties.
      type: object
      properties:
        partnerCustomerId:
          description: |
            Optional. The partner's unique identifier for the end user. Bango treats this as an opaque string, which must not be empty.
          type: string
          minLength: 1
          example: 6789812A
        OTHER:
          description: |
            Any other private data. TBD: constraints; other common properties, if any.
    nextAction:
      description: |
        An optional next action for either the merchant partner or the payment provider. This string, read/write for both parties, allows either party to send an explicit signal to the other using a well-defined property. Either party may set the string as part of an "update shared data" operation.

        Typically the string is used by one party to inform the other party that there is session data for them to process to progress the negotation. That session data should provide additional context as needed.

        For flexibility, this schema specifies any string. Bango recommends using these strings:
        - `none`: No next action is currently defined
        - `merchant`: A signal for the merchant partner to take the next action
        - `payment-provider`: A signal for the payment provider to take the next action
      type: string
      minLength: 1
      default: none
    merchantToPaymentProvider:
      description: |
        Data the merchant partner owns (read/write access) and the payment provider may consume (read access only).

        This specification defines some properties that merchant partners and payment providers MAY use for certain purposes. These properties are optional, but if specified MUST match the schemas defined here.

        Merchant partners and payment providers MAY use other properties not defined here.
      type: object
      properties:
        authSuccessRedirectUrl:
          description: |
            The merchant URL to which the payment provider should redirect the end user after a successful authentication.
          type: string
          format: url
          example: https://example.com/merchant/user-login-ok
        authFailureRedirectUrl:
          description: |
            The merchant URL to which the payment provider should redirect the end user after a failed authentication.
          type: string
          format: url
          example: https://example.com/merchant/user-login-failed
    phone-number:
      title: Phone number (E.164)
      description: |
        A phone number in E.164 format, with a leading `+` sign. No spaces or symbols are permitted.
      type: string
      pattern: ^\+[1-9]?[0-9]{7,14}$
      example: '+447700900123'
    payment-instrument-account-properties:
      title: Payment instrument account properties
      description: |
        Properties of a payment instrument that identify the account with the payment provider. In many cases, this is a phone number.

        MUST contain at least one property. MAY contain more than one property. All property values MUST be strings.

        The `phoneNumber` property defined here MUST be used IF the payment provider identifies the account using a phone number that can be expressed in E.164 format with a leading `+`. Otherwise, the property MUST NOT be used (use a property with a different name instead).
      type: object
      minProperties: 1
      maxProperties: 50
      unevaluatedProperties:
        type: string
        minLength: 1
        maxLength: 512
      properties:
        phoneNumber:
          $ref: '#/components/schemas/phone-number'
      example:
        phoneNumber: '+447700900123'
        anyPropertyNeededByThePaymentProvider: some-string
    payment-provider-id:
      title: Payment provider ID
      description: |
        Friendly unique identifier for the payment provider.

        Internally, corresponds to the `accountKey` property in the route-config-server's partner_namespaces table.
      x-bango-public-description: |
        Friendly unique identifier for the payment provider.
      type: string
      example: OGNABTEL
      minLength: 2
      maxLength: 50
    simple-object-patch:
      title: Simple object patch mechanism
      description: |
        Extend an existing object schema with this schema to enable a simple way to patch an object.

        The extended schema has two special properties:
        - $replace: boolean. If present, and if true, then this means "remove all existing properties from the object before applying updates"
        - $remove: an array of property names. If present, then this means "remove properties with these names from the object before applying updates"

        This extended schema now lets you define a patch object, which specifies operations to perform on an existing object to make a new object. In the patch object, `$replace` and `$remove` (applied first) remove existing properties from the original object, and other properties update the original object.

        Nested objects might themselves be extended this way: patches are applied recursively.

        Examples

        Imagine a schema ABC defining three optional properties `a`, `b`, and `c` whose values are all strings. Consider this object matching schema ABC:

        ```json
        {
          "a": "xyz",
          "b": "qwerty",
          "c": "plplpl"
        }
        ```

        Extend ABC with this schema (adding `$remove` and `$replace`) to get ABC_Patchable. Here's a patch object matching ABC_Patchable:

        ```json
        {
          "$remove": ["b"],
          "a": "aaaaaaa"
        }
        ```

        Applying the patch - combining the original object with the patch object - gives this object:

        ```json
        {
          "a": "aaaaaaa",
          "c": "plplpl"
        }
        ```

        - The property `b` was removed (because of `$remove` in the patch object)
        - The property `a` was updated (because it was specified in the patch object)
        - The property `c` was unchanged (because it wasn't mentioned in the patch object)

        Another example of a patch object:

        ```json
        {
          "$replace": true,
          "b": "bbbbbbb"
        }
        ```

        The result after patching the original object would be:

        ```json
        {
          "b": "bbbbbbb"
        }
        ```

        - All existing properties were removed (because `$replace` was set to true in the patch object)
        - The property `b` was updated (because it was specified in the patch object)

        Now imagine a schema GH defining two properties `g` and `h`, where the value of `g` is a string and the value of `h` is an object (matching schema XY) with optional properties `x` and `y`, both strings. Consider this object matching schema GH:

        ```json
        {
          "g": "ggg",
          "h": {
            "x": "xxx",
            "y": "yyy"
          }
        }
        ```

        Extend both GH and the nested XY schemas with this schema, making GH_Patchable. Here's a patch object matching GH_Patchable:

        ```json
        {
          "$remove": ['g'],
          "h": {
            "$replace": true,
            "x": "aaa"
          }
        }
        ```

        The result after patching the object above would be:

        ```json
        {
          "h": {
            "x": "aaa"
          }
        }
        ```

        - The property `g` was removed (because of `$remove` in the patch object)
        - The properties `x` and `y` were removed (because `$replace` was set to true in the inner patch object)
        - The property `x` was updated (because it was specifed in the inner patch object)
      type: object
      properties:
        $replace:
          description: |
            If true, removes all existing properties from the object before applying any property updates.
          type: boolean
          default: false
        $remove:
          description: |
            If present, removes the properties named in the array before applying any property updates.

            It is NOT an error if an array member references a property that does not exist in the object being patched.

            It is NOT an error if an array member references a property not defined in the schema of the object being patched.

            It is NOT an error to include a property in the array and also to update its value.
          type: array
          items:
            type: string
    START_TRUSTED_FLOW:
      title: START_TRUSTED_FLOW action
      description: |
        A request to use the Trusted flow to obtain a payment instrument token.
      type: object
      properties:
        type:
          const: START_TRUSTED_FLOW
        payload:
          description: |
            Data needed for the START_TRUSTED_FLOW action.
          type: object
          properties:
            account:
              $ref: '#/components/schemas/payment-instrument-account-properties'
            paymentProviderId:
              $ref: '#/components/schemas/payment-provider-id'
            private:
              allOf:
                - $ref: '#/components/schemas/simple-object-patch'
                - $ref: '#/components/schemas/private'
                - title: Patch object for the private data related to the identity verification session
          required:
            - phoneNumber
            - paymentProviderId
      required:
        - type
        - payload
    START_NEGOTIATED_FLOW:
      title: START_NEGOTIATED_FLOW action
      description: |
        A request to use the Negotiated flow to obtain a payment instrument token.
      type: object
      properties:
        type:
          const: START_NEGOTIATED_FLOW
        payload:
          description: |
            Data needed for the START_NEGOTIATED_FLOW action.
          type: object
          properties:
            paymentProviderId:
              $ref: '#/components/schemas/payment-provider-id'
            private:
              allOf:
                - $ref: '#/components/schemas/simple-object-patch'
                - $ref: '#/components/schemas/private'
                - title: Patch object for the private data related to the identity verification session
            shared:
              description: |
                Update to the data shared from the merchant partner to the payment provider. Data in `merchantToPaymentProvider` is merged into the existing data.
              type: object
              properties:
                nextAction:
                  $ref: '#/components/schemas/nextAction'
                merchantToPaymentProvider:
                  $ref: '#/components/schemas/merchantToPaymentProvider'
          required:
            - paymentProviderId
      required:
        - type
        - payload
    START_MO_FLOW:
      title: START_MO_FLOW action
      description: |
        A request to use the MO flow to obtain a payment instrument token.
      type: object
      properties:
        type:
          const: START_MO_FLOW
        payload:
          description: |
            Data needed for the START_MO_FLOW action.
          type: object
          properties:
            paymentProviderId:
              $ref: '#/components/schemas/payment-provider-id'
            private:
              allOf:
                - $ref: '#/components/schemas/simple-object-patch'
                - $ref: '#/components/schemas/private'
                - title: Patch object for the private data related to the identity verification session
          required:
            - paymentProviderId
      required:
        - type
        - payload
    locale-bcp-47:
      title: BCP 47 language tag
      description: |
        A [BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) language tag.
      type: string
      minLength: 1
      maxLength: 50
      examples:
        - en-US
        - ar-SA
    START_MT_FLOW:
      title: START_MT_FLOW action
      description: |
        A request to use the MT flow to obtain a payment instrument token.
      type: object
      properties:
        type:
          const: START_MT_FLOW
        payload:
          description: |
            Data needed for the START_MT_FLOW action.
          type: object
          properties:
            paymentProviderId:
              $ref: '#/components/schemas/payment-provider-id'
            account:
              $ref: '#/components/schemas/payment-instrument-account-properties'
            message:
              description: |
                Details of the message template and values that replace placeholder fields in the template.

                All `message` properties are optional, with default values determined by the Bango Platform.
              type: object
              properties:
                template:
                  description: |
                    Text for the message sent to the end user's device, including placeholders in braces. The Bango Platform replaces these placeholders with appropriate values when it sends the message to the end user's device.

                    Available placeholders:
                    - `{otp}` - mandatory - replaced with the appropriate OTP
                    - `{merchantName}` - optional - replaced with the value of `message.merchantName` if present, or the merchant name in the billing route configuration, or the merchant partner name defined in the Bango Platform for the namespace ID in the request URL

                    Default value: the template defined in the billing route configuration, or a hardcoded template.
                  type: string
                  minLength: 5
                  maxLength: 500
                  pattern: '{otp}'
                  example: '{otp} is the PIN for {merchantName}'
                merchantName:
                  description: |
                    Merchant name to display in the message sent to the end user's device.

                    Default value: the merchant name in the billing route configuration, or the merchant partner name defined in the Bango Platform for the namespace ID in the request URL
                  type: string
                  minLength: 1
                  maxLength: 100
                  example: Aussie Apps
                locale:
                  $ref: '#/components/schemas/locale-bcp-47'
                  description: |
                    A [BCP 47](https://en.wikipedia.org/wiki/IETF_language_tag) language tag. The Bango Platform uses this value to select the most appropriate message template if `message.template` is omitted.

                    Default value: the locale defined in the billing route configuration, or en-US
              additionalProperties: false
            private:
              allOf:
                - $ref: '#/components/schemas/simple-object-patch'
                - $ref: '#/components/schemas/private'
                - title: Patch object for the private data related to the identity verification session
          additionalProperties: false
          required:
            - paymentProviderId
            - account
      additionalProperties: false
      required:
        - type
        - payload
    CANCEL_SESSION:
      title: CANCEL_SESSION action [plan-later]
      description: |
        A request to cancel the session. Any flow currently in progress is ended, and the `state` moves to `closed`.
      type: object
      properties:
        type:
          const: CANCEL_SESSION
        payload:
          description: Empty object
          type: object
          additionalProperties: false
      required:
        - type
        - payload
    action:
      description: |
        Optional action to send immediately after a successful resource creation.
      oneOf:
        - $ref: '#/components/schemas/START_TRUSTED_FLOW'
        - $ref: '#/components/schemas/START_NEGOTIATED_FLOW'
        - $ref: '#/components/schemas/START_MO_FLOW'
        - $ref: '#/components/schemas/START_MT_FLOW'
        - $ref: '#/components/schemas/CANCEL_SESSION'
    resource-id:
      title: Resource ID
      description: |
        Globally unique resource ID. These IDs are opaque, not guessable, and not sequential.

        Each individual resource in a partner's namespace has a unique identifier: this is the identifier immediately after the resource type in the URI path.

        For example, in the URI `/ns/673c74de-ce5b-4f79-9851-2544d1d836cb/elephants/581b2e40-741c-4683-ae66-46c9fe6f4d5e`:
        - The namespace id is `673c74de-ce5b-4f79-9851-2544d1d836cbde`
        - `elephants` indicates the resource type is `elephant`
        - The resource id is `581b2e40-741c-4683-ae66-46c9fe6f4d5e`

        Every resource has a read-only property `rid` that contains the resource ID, for convenience.
      type: string
      format: uuid
      example: 581b2e40-741c-4683-ae66-46c9fe6f4d5e
    lastUpdate:
      type: string
      format: date-time
      description: |
        RFC 3339 datetime of the last update to this resource
      example: '2022-12-21T08:59:32Z'
    identity-session-shared:
      title: Shared identity verification session properties
      description: |
        Data shared between the merchant partner and the payment provider as part of an identity verification session.
      type: object
      properties:
        nextAction:
          description: |
            An optional next action for either the merchant partner or the payment provider. This string, read/write for both parties, allows either party to send an explicit signal to the other using a well-defined property. Either party may set the string as part of an "update shared data" operation.

            Typically the string is used by one party to inform the other party that there is session data for them to process to progress the negotation. That session data should provide additional context as needed.

            For flexibility, this schema specifies any string. Bango recommends using these strings:
            - `none`: No next action is currently defined
            - `merchant`: A signal for the merchant partner to take the next action
            - `payment-provider`: A signal for the payment provider to take the next action
          type: string
          minLength: 1
          default: none
        merchantToPaymentProvider:
          description: |
            Data the merchant partner owns (read/write access) and the payment provider may consume (read access only).

            This specification defines some properties that merchant partners and payment providers MAY use for certain purposes. These properties are optional, but if specified MUST match the schemas defined here.

            Merchant partners and payment providers MAY use other properties not defined here.
          type: object
          properties:
            authSuccessRedirectUrl:
              description: |
                The merchant URL to which the payment provider should redirect the end user after a successful authentication.
              type: string
              format: url
              example: https://example.com/merchant/user-login-ok
            authFailureRedirectUrl:
              description: |
                The merchant URL to which the payment provider should redirect the end user after a failed authentication.
              type: string
              format: url
              example: https://example.com/merchant/user-login-failed
        paymentProviderToMerchant:
          description: |
            Data the payment provider owns (read/write access) and the merchant partner may consue (read access only)
          type: object
          properties:
            authRedirectUrl:
              description: |
                The payment provider URL to which the merchant should redirect the end user to authenticate to the payment provider.
              type: string
              format: url
              example: https://example.com/payment-provider/login
    flow-none:
      const: none
      description: |
        No flow has been selected
    state-flow-none:
      description: |
        Describes the state of the resource when no flow has been selected.

        `state` is one of:
        - `authorizing` - the Bango Platform is checking for permission to create the session
        - `new` - the session is created and the Bango Platform is ready for the partner to select a flow
        - `failed` - the Bango Platform has denied the request to create the session
        - `closed` - the partner has decided to cancel the session without selecting a flow

        Typically partners see only `new`. `authorizing` is very short-lived, `failed` is possible but unlikely, and `closed` is only entered at the partner's request.
      type: string
      enum:
        - authorizing
        - new
        - failed
        - closed
    missing-parameter:
      title: missing-parameter
      description: A required parameter is missing from the request
      type: object
      properties:
        code:
          const: missing-parameter
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            param:
              description: The name of the missing parameter
              type: string
          required:
            - param
        message:
          description: Human-readable message describing the error
          type: string
          example: A required parameter was missing from the request
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/missing-parameter
      required:
        - code
        - meta
        - message
    invalid-parameter:
      title: invalid-parameter
      description: A request parameter is invalid
      type: object
      properties:
        code:
          const: invalid-parameter
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            param:
              description: The name of the invalid parameter
              type: string
            reason:
              description: Optional human-readable information to explain why the parameter is invalid. Code must not rely on the content of this string.
              type: string
              example: 'Expected format: YYYY-MM-DD'
          required:
            - param
        message:
          description: Human-readable message describing the error
          type: string
          example: A parameter in the request was not valid
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/invalid-parameter
      required:
        - code
        - meta
        - message
    incompatible-state:
      title: incompatible-state
      description: |
        Incompatible state.

        This is a generic error used when a more specific error is not available. The `meta.reason` may give a human-readable description of the error.
      type: object
      properties:
        code:
          const: incompatible-state
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            reason:
              description: Human-readable information to explain in detail why the operation cannot be permitted in the current state. Code must not rely on the content of this string.
              type: string
              example: Operation is permitted in state "active" only
        message:
          description: Human-readable message describing the error
          const: The resource is not in the correct state for the requested operation
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/incompatible-state
      required:
        - code
        - meta
        - message
    internal-server-error:
      title: internal-server-error
      description: Internal server error
      type: object
      properties:
        code:
          const: internal-server-error
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            canRetry:
              description: Whether the request can be retried
              type: boolean
              default: true
        message:
          description: Human-readable message describing the error
          type: string
          example: The server encountered an unexpected condition which prevented it from fulfilling the request
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/internal-server-error
      required:
        - code
        - meta
        - message
    service-unavailable:
      title: service-unavailable
      description: Service is unavailable
      type: object
      properties:
        code:
          const: service-unavailable
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: The service is undergoing maintenance and is not available. Please try again later
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/service-unavailable
      required:
        - code
        - meta
        - message
    user-canceled:
      title: user-canceled
      description: |
        The payment provider denied a requested action because the user canceled.
      type: object
      properties:
        code:
          const: user-canceled
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/user-canceled
      required:
        - code
        - meta
        - message
    expired:
      title: expired
      description: |
        The payment provider denied a requested action because the authority to perform the action has expired.

        For example, if too much time has passed since a payment was authorized, the payment provider might return an `expired` error.
      type: object
      properties:
        code:
          const: expired
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/expired
      required:
        - code
        - meta
        - message
    payment-provider-failure:
      title: payment-provider-failure
      description: |
        An error occurred with the downstream payment provider, and the Bango Platform was unable to fulfil the request.

        This might be a transient error or a persistent error. The `meta.paymentProviderCode` value indicates the type of response received by the Bango Platform from the payment provider.

        The `meta.canRetry` boolean indicates whether the payment provider believes the merchant can retry the request.
      type: object
      properties:
        code:
          const: payment-provider-failure
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            paymentProviderCode:
              description: |
                Code indicating the type of response the Bango Platform received from the payment provider. Not all codes apply to all requests from the Bango Platform.

                Possible values:
                - `service-unavailable`: the payment provider returned an HTTP 503 response to a request from the Bango Platform
                - `internal-server-error`: the payment provider returned another HTTP 5xx response to a request from the Bango Platform
                - `mt-message-send-request-failure`: the payment provider was unable to send an MT flow message to an end user's device
                - `otp-request-failure`: the payment provider was unable to send an OTP to an end user's device, or verify an OTP provided by an end user
              type: string
              enum:
                - internal-server-error
                - service-unavailable
                - mt-message-send-request-failure
                - otp-request-failure
            canRetry:
              description: Whether the payment provider believes the request can be retried
              type: boolean
          required:
            - paymentProviderCode
            - canRetry
        message:
          description: Human-readable message describing the error
          const: An error occurred at the payment provider
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/payment-provider-failure
      required:
        - code
        - meta
        - message
    merchant-failure:
      title: merchant-failure
      description: |
        An error occurred with the upstream merchant, and the Bango Platform was unable to fulfil the request.

        This might be a transient error or a persistent error. The `meta.merchantCode` value indicates the type of response received by the Bango Platform from the merchant.
      type: object
      properties:
        code:
          const: merchant-failure
        meta:
          description: Additional information to help identify the specific error case
          type: object
          properties:
            merchantCode:
              description: |
                Code indicating the type of response received by the Bango Platform from the merchant.
              type: string
              enum:
                - internal-server-error
                - service-unavailable
          required:
            - merchantCode
        message:
          description: Human-readable message describing the error
          const: An error occurred at the merchant
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/merchant-failure
      required:
        - code
        - meta
        - message
    user-invalid:
      title: user-invalid
      description: |
        The payment provider denied a requested action because the user does not exist or is invalid in some way.
      type: object
      properties:
        code:
          const: user-invalid
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/user-invalid
      required:
        - code
        - meta
        - message
    user-barred:
      title: user-barred
      description: |
        The requested action was denied because the user has been barred.
      type: object
      properties:
        code:
          const: user-barred
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/user-barred
      required:
        - code
        - meta
        - message
    user-suspended:
      title: user-suspended
      description: |
        The payment provider denied a requested action because the user has been suspended.
      type: object
      properties:
        code:
          const: user-suspended
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/user-suspended
      required:
        - code
        - meta
        - message
    user-not-enabled:
      title: user-not-enabled
      description: |
        The requested action was denied because the user is not currently enabled.
      type: object
      properties:
        code:
          const: user-not-enabled
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/user-not-enabled
      required:
        - code
        - meta
        - message
    rejected:
      title: rejected
      description: |
        The responsible partner decided not to confirm the identity of an end user as part of an identity verification flow, and did not supply a specific error code. The `message` may contain more information.

        The identity verification flow for the session determines whether the responsible partner is the payment provider or the merchant.
      type: object
      properties:
        code:
          const: rejected
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/rejected
      required:
        - code
        - meta
        - message
    operation-not-supported:
      title: operation-not-supported
      description: |
        The payment provider denied a requested action because it does not support the operation.
      type: object
      properties:
        code:
          const: operation-not-supported
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/operation-not-supported
      required:
        - code
        - meta
        - message
    denied:
      title: denied
      description: |
        The payment provider denied a requested action without supplying a specific error code. The `message` may contain more information.
      type: object
      properties:
        code:
          const: denied
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          type: string
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/denied
      required:
        - code
        - meta
        - message
    unauthorized-flow:
      title: unauthorized-flow
      description: |
        The merchant is not authorized to use the requested flow.
      type: object
      properties:
        code:
          const: unauthorized-flow
        meta:
          description: Empty in this case
          type: object
        message:
          description: Human-readable message describing the error
          const: Not authorized to start requested flow
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/unauthorized-flow
      required:
        - code
        - meta
        - message
    result-flow-any:
      title: Action result, if any
      description: |
        The result of the most recent action. There are three outcomes for an action:

        1. The action was performed and completed with a positive outcome
        2. The action was performed and completed with a negative outcome
        3. The action was not performed because a required constraint was not met

        The result `code` indicates which outcome applied and is always a string in `lower-kebab-case`.

        The result `reasons` indicates any additional explanations available for the outcome (outcomes 2 and 3 above). For outcome 1 above, `reasons` is an empty array.
      type: object
      properties:
        code:
          description: |
            The outcome of the most recent action. This value gives you a high-level idea of _what happened_.
          type: string
          enum:
            - create-denied
            - create-failed
            - flow-denied
            - flow-failed
            - token-created
          example: token-created
        reasons:
          description: |
            Any explanations available to describe the outcome of the most recent action
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/missing-parameter'
              - $ref: '#/components/schemas/invalid-parameter'
              - $ref: '#/components/schemas/incompatible-state'
              - $ref: '#/components/schemas/internal-server-error'
              - $ref: '#/components/schemas/service-unavailable'
              - $ref: '#/components/schemas/user-canceled'
              - $ref: '#/components/schemas/expired'
              - $ref: '#/components/schemas/payment-provider-failure'
              - $ref: '#/components/schemas/merchant-failure'
              - $ref: '#/components/schemas/user-invalid'
              - $ref: '#/components/schemas/user-barred'
              - $ref: '#/components/schemas/user-suspended'
              - $ref: '#/components/schemas/user-not-enabled'
              - $ref: '#/components/schemas/rejected'
              - $ref: '#/components/schemas/operation-not-supported'
              - $ref: '#/components/schemas/denied'
              - $ref: '#/components/schemas/unauthorized-flow'
      required:
        - code
        - reasons
    session-flow-none:
      title: Identity verification session - no flow selected
      description: |
        An identity verification session when no flow has been selected.
      type: object
      properties:
        rid:
          $ref: '#/components/schemas/resource-id'
        lastUpdate:
          $ref: '#/components/schemas/lastUpdate'
        partnerSessionId:
          $ref: '#/components/schemas/partnerSessionId'
        private:
          $ref: '#/components/schemas/private'
        shared:
          $ref: '#/components/schemas/identity-session-shared'
        flow:
          $ref: '#/components/schemas/flow-none'
        state:
          $ref: '#/components/schemas/state-flow-none'
        result:
          $ref: '#/components/schemas/result-flow-any'
      additionalProperties: false
      required:
        - rid
        - lastUpdate
        - flow
        - state
    flow-trusted:
      description: |
        Indicates the `trusted` identity verification flow was selected.
      const: trusted
    state-flow-trusted:
      description: |
        Describes the state of the resource when the Trusted flow has been selected.

        `state` is one of:
        - `authorizing` - the Bango Platform is checking for permission to start the flow
        - `creating-token` - the Bango Platform is obtaining the payment instrument token
        - `succeeded` - the Bango Platform has successfully obtained the payment instrument token (it's a property on the resource)
        - `failed` - the Bango Platform has denied the request to start the flow

        Typically partners only see `succeeded`. `authorizing` and `creating-token` are short-lived, and `failed` occurs when the partner is not authorized for this flow.
      type: string
      enum:
        - authorizing
        - creating-token
        - succeeded
        - failed
    paymentInstrumentToken-flow-trusted:
      description: |
        The payment instrument token obtained by the Bango Platform for the partner's end user.

        Only present in the resource when `state` is `succeeded`.
      type: string
      format: uuid
    session-flow-trusted:
      title: Identity verification session - Trusted flow selected
      description: |
        An identity verification session when the Trusted flow has been selected.
      type: object
      properties:
        rid:
          $ref: '#/components/schemas/resource-id'
        lastUpdate:
          $ref: '#/components/schemas/lastUpdate'
        partnerSessionId:
          $ref: '#/components/schemas/partnerSessionId'
        paymentProviderId:
          $ref: '#/components/schemas/payment-provider-id'
        private:
          $ref: '#/components/schemas/private'
        shared:
          $ref: '#/components/schemas/identity-session-shared'
        flow:
          $ref: '#/components/schemas/flow-trusted'
        state:
          $ref: '#/components/schemas/state-flow-trusted'
        result:
          $ref: '#/components/schemas/result-flow-any'
        paymentInstrumentToken:
          $ref: '#/components/schemas/paymentInstrumentToken-flow-trusted'
      additionalProperties: false
      required:
        - rid
        - lastUpdate
        - flow
        - state
    flow-negotiated:
      description: |
        Indicates the `negotiated` identity verification flow was selected.
      const: negotiated
    state-flow-negotiated:
      description: |
        Describes the state of the resource when the Negotiated flow has been selected.

        `state` is one of:
        - `authorizing` - the Bango Platform is checking for permission to start the flow
        - `awaiting-confirmation` - the Bango Platform is awaiting confirmation of the end user's identity from the payment provider
        - `creating-token` - the payment provider confirmed the end user's identity and the Bango Platform is obtaining the payment instrument token
        - `succeeded` - the Bango Platform has successfully obtained the payment instrument token (it's a property on the resource)
        - `failed` - the Bango Platform has denied the request to start the flow, or the payment provider rejected the attempt to identify the end user

        Typically partners only see `awaiting-confirmation`,  and `succeeded`. `authorizing` and `creating-token` are short-lived, and `failed` occurs when the partner is not authorized for this flow.
      type: string
      enum:
        - authorizing
        - awaiting-confirmation
        - creating-token
        - succeeded
        - failed
    paymentInstrumentToken-flow-negotiated:
      description: |
        The payment instrument token obtained by the Bango Platform for the partner's end user.

        Only present in the resource when `state` is `succeeded`.
      type: string
      format: uuid
    session-flow-negotiated:
      title: Identity verification session - Negotiated flow selected
      description: |
        An identity verification session when the Negotiated flow has been selected.
      type: object
      properties:
        rid:
          $ref: '#/components/schemas/resource-id'
        lastUpdate:
          $ref: '#/components/schemas/lastUpdate'
        partnerSessionId:
          $ref: '#/components/schemas/partnerSessionId'
        paymentProviderId:
          $ref: '#/components/schemas/payment-provider-id'
        private:
          $ref: '#/components/schemas/private'
        shared:
          $ref: '#/components/schemas/identity-session-shared'
        flow:
          $ref: '#/components/schemas/flow-negotiated'
        state:
          $ref: '#/components/schemas/state-flow-negotiated'
        result:
          $ref: '#/components/schemas/result-flow-any'
        paymentInstrumentToken:
          $ref: '#/components/schemas/paymentInstrumentToken-flow-negotiated'
      additionalProperties: false
      required:
        - rid
        - lastUpdate
        - flow
        - state
    flow-mo:
      description: |
        Indicates the `mo` identity verification flow was selected.
      const: mo
    state-flow-mo:
      description: |
        Describes the state of the resource when the MO flow has been selected.

        `state` is one of:
        - `authorizing` - the Bango Platform is checking for permission to start the flow
        - `awaiting-message` - the Bango Platform is waiting for the MO message from the payment provider
        - `awaiting-confirmation` - the Bango Platform is awaiting confirmation of the end user's identity from the merchant
        - `creating-token` - the payment provider confirmed the end user's identity and the Bango Platform is obtaining the payment instrument token
        - `succeeded` - the Bango Platform has successfully obtained the payment instrument token (it's a property on the resource)
        - `failed` - the Bango Platform has denied the request to start the flow, or the merchant rejected the attempt to identify the end user, or there was a problem with the MO message

        Typically partners only see `awaiting-message`, `awaiting-confirmation`, and `succeeded`. `authorizing` and `creating-token` are short-lived, and `failed` occurs in case of errors.
      type: string
      enum:
        - authorizing
        - awaiting-message
        - awaiting-confirmation
        - creating-token
        - succeeded
        - failed
    shortcode-flow-mo:
      description: |
        Shortcode the merchant must use to send the message to the payment provider.

        Sourced from billing-route-service.

        Omitted if we don't need to tell the merchant, or if the merchant did not create the verification session itself.
      type: string
      pattern: ^[0-9]{1,20}$
      example: '12345'
    messageBody-flow-mo:
      description: |
        The full text of the message the merchant must send from the end user's device to the payment provider (using the shortcode if supplied).

        Static string `bango-session-rid:` followed by the verification session rid. Always exactly 54 bytes.

        Omitted if the merchant did not create the verification session itself. Present if it did.
      type: string
      minLength: 54
      maxLength: 54
      example: bango-session-rid:68aec572-c34e-4f68-aa80-10300c4dc06b
    mo-transport:
      title: MO transport mechanism
      description: |
        How the MO message was delivered to the payment provider.

        Permitted values:
        - `sms`: MO message was delivered over SMS
        - `http-header-enrichment`: MO message was delivered over HTTP with user account details provided using Header Enrichment
      type: string
      enum:
        - sms
        - http-header-enrichment
    paymentInstrumentToken-flow-mo:
      description: |
        The payment instrument token obtained by the Bango Platform for the partner's end user.

        Only present in the resource when `state` is `succeeded`.
      type: string
      format: uuid
    partner-billing-token:
      title: Partner billing token
      description: |
        A partner billing token to be used later by the partner in payment transactions.

        It may be present only after being provided by the partner in a previous confirm session identity request.
      type: string
      minLength: 1
      maxLength: 100
    session-flow-mo:
      title: Identity verification session - MO flow selected
      description: |
        An identity verification session when the MO flow has been selected.
      type: object
      properties:
        rid:
          $ref: '#/components/schemas/resource-id'
        lastUpdate:
          $ref: '#/components/schemas/lastUpdate'
        partnerSessionId:
          $ref: '#/components/schemas/partnerSessionId'
        paymentProviderId:
          $ref: '#/components/schemas/payment-provider-id'
        private:
          $ref: '#/components/schemas/private'
        shared:
          $ref: '#/components/schemas/identity-session-shared'
        flow:
          $ref: '#/components/schemas/flow-mo'
        state:
          $ref: '#/components/schemas/state-flow-mo'
        shortcode:
          $ref: '#/components/schemas/shortcode-flow-mo'
        messageBody:
          $ref: '#/components/schemas/messageBody-flow-mo'
        transport:
          $ref: '#/components/schemas/mo-transport'
        result:
          $ref: '#/components/schemas/result-flow-any'
        paymentInstrumentToken:
          $ref: '#/components/schemas/paymentInstrumentToken-flow-mo'
        partnerBillingToken:
          $ref: '#/components/schemas/partner-billing-token'
      additionalProperties: false
      required:
        - rid
        - lastUpdate
        - flow
        - state
    flow-mt:
      description: |
        Indicates the `mt` identity verification flow was selected.
      const: mt
    state-flow-mt:
      description: |
        Describes the state of the resource when the MT flow has been selected.

        `state` is one of:
        - `authorizing` - the Bango Platform is checking for permission to start the flow
        - `processing-otp` - the Bango Platform is creating, validating, renewing, or resetting an OTP
        - `processing-pp-otp` - the Bango Platform has asked the payment provider to send or verify an OTP
        - `sending-otp` - the Bango Platform has asked the payment provider to send the OTP to the user, and is waiting for a response
        - `awaiting-user-otp` - the Bango Platform is waiting for the merchant to send an action related to the OTP: verify, reset, or resent
        - `creating-token` - the merchant end user entered the OTP correctly and the Bango Platform is obtaining the payment instrument token
        - `succeeded` - the Bango Platform has successfully obtained the payment instrument token (it's a property on the resource)
        - `failed` - the Bango Platform has denied the request to start the flow, or the payment provider fatally denied the request to send the MT message to the end user, or a service error occurred

        Typically partners only see `awaiting-user-otp` and `succeeded`. `authorizing`, `processing-otp`, `processing-pp-otp`, `sending-otp`, and `creating-token` are short-lived, and `failed` occurs in case of errors.
      type: string
      enum:
        - authorizing
        - processing-otp
        - processing-pp-otp
        - sending-otp
        - awaiting-user-otp
        - creating-token
        - succeeded
        - failed
    otp-flow-mt:
      title: OTP properties
      description: |
        Properties useful to the merchant about the current OTP and retries and resets available. Only used for Bango-managed OTPs.
      type: object
      additionalProperties: false
      properties:
        triesUntilReset:
          description: |
            How many attempts remain for the merchant end user to type the current OTP before a reset occurs, if available
          type: integer
          minimum: 0
          example: 3
        resetsAvailable:
          description: |
            How many times the merchant may request to generate a new OTP within the session. When `triesUntilReset` and `resetsAvailable` are both zero, the session ends in failure.
          type: integer
          minimum: 0
          example: 5
        validUntil:
          description: |
            RFC 3339 datetime after which the current OTP expires. On expiry, any attempt to verify the OTP fails and a reset occurs, if available
          type: string
          format: date-time
          example: '2024-02-06T18:31:36Z'
    result-flow-mt:
      title: Action result, if any
      description: |
        The result of the most recent action.

        The result `code` indicates what happened and is always a string in `lower-kebab-case`.

        The result `reasons` indicates any additional explanations available. It might be an empty array.
      type: object
      properties:
        code:
          description: |
            The outcome of the most recent action. This value gives you a high-level idea of _what happened_.

            Route configuration identifies which actor manages OTPs for the flow: either the Bango Platform or the payment provider.
            - Values marked with [B] are returned only when the Bango Platform manages the OTPs
            - Values marked with [PP] are returned only when the payment provider manages the OTPs
            - Values without a marker are returned in either case

            Possible values:
            - `create-denied`
              - Bango Platform denied the request to create the session
            - `create-failed`
              - Bango Platform encountered an error while creating the session
            - `flow-denied`
              - Bango Platform or payment provider denied the request to start a flow. Occurs if the payment provider doesn't recognize the account properties supplied
            - `flow-failed`
              - Bango Platform encountered an error while performing an internal operation
            - `token-created`
             - Bango Platform successfully created the payment instrument token
            - `otp-created-send-requested` [B]
              - Merchant started flow
              - Bango Platform generated the first OTP and asked the payment provider to send it to the end user
            - `otp-reset-send-requested` [B]
              - Merchant requested RESET, or RESEND of an expired OTP
              - Bango Platform reset the OTP, and asked the payment provider to send it to the end user
            - `otp-resend-requested` [B]
              - Merchant requested RESEND of an unexpired OTP
              - Bango Platform reset the expiry date and asked the payment provider to send the current OTP to the end user again
            - `otp-expired-send-requested` [B]
              - Merchant requested VERIFY of an expired OTP
              - Bango Platform generated a new OTP and asked the payment provider to send it to the end user
            - `otp-incorrect-send-requested` [B]
              - Merchant requested VERIFY of an unexpired OTP, the supplied OTP was incorrect, no more attempts remain for that OTP, but resets are available
              - Bango Platform generated a new OTP and asked the payment provider to send it to the end user
            - `otp-send-requested` [PP]
              - Bango Platform asked the payment provider to generate and send an OTP to the end user, or send an unexpired OTP it generated earlier
            - `otp-send-request-denied` [PP]
              - Bango Platform asked the payment provider to generate and send an OTP to the end user, or send an unexpired OTP it generated earlier, but payment provider denied the request for security reasons
            - `otp-send-request-failure` [B]
              - Any merchant action
              - Bango Platform asked the payment provider to send an OTP to the end user, and the payment provider did not accept the request
              - Merchant should RESEND
            - `otp-expired-must-resend` [B]
              - Merchant requested VERIFY of an expired OTP
              - Bango Platform generated a new OTP
              - Bango Platform is configured to wait for the merchant to request RESEND
            - `otp-expired` [PP]
              - Merchant requested VERIFY, and the payment provider reported that the OTP has expired. Merchant should request RESET
            - `otp-incorrect-must-resend` [B]
              - Merchant requested VERIFY of an unexpired OTP, the supplied OTP was incorrect, no more attempts remain for that OTP, but resets are available
              - Bango Platform generated a new OTP
              - Bango Platform is configured to wait for the merchant to request RESEND
            - `otp-incorrect`
              - Merchant requested VERIFY of an unexpired OTP, and the supplied OTP was incorrect. For a Bango-managed OTP, more attempts remain for that OTP. For a payment-provider-managed OTP, more attempts MIGHT remain
              - Merchant can request VERIFY again, or RESET, or RESEND
            - `otp-reset-not-available` [B]
              - Merchant requested RESET and more attempts are available but no resets, OR
              - Merchant requested RESEND of an expired OTP and no resets are available
            - `otp-incorrect-final-attempt`
              - Merchant requested VERIFY, the supplied OTP was incorrect, and now there are no more retries or resets available
              - Bango Platform closed the session in state `failed`
            - `session-ended` [B]
              - Merchant requested VERIFY when no retries or resets are available, OR
              - Merchant requested RESET when no retries or resets are available, OR
              - Merchant requested RESEND of an expired OTP and no retries or resets are available
            - `flow-temporary-error` [B]
              - Bango Platform encountered a temporary internal error
              - Merchant should try again
            - `pp-otp-error` [PP]
              - Bango Platform asked the payment provider to send an OTP to a merchant end user, or verify an OTP supplied by a merchant end user, and an error occurred at the payment provider
              - Merchant should try again
            - `unknown`
              - An unknown error occurred
              - Merchant should try again
          type: string
          enum:
            - create-denied
            - create-failed
            - flow-denied
            - flow-failed
            - token-created
            - otp-created-send-requested
            - otp-reset-send-requested
            - otp-resend-requested
            - otp-expired-send-requested
            - otp-incorrect-send-requested
            - otp-send-requested
            - otp-send-request-denied
            - otp-send-request-failure
            - otp-expired-must-resend
            - otp-expired
            - otp-incorrect-must-resend
            - otp-incorrect
            - otp-reset-not-available
            - otp-incorrect-final-attempt
            - session-ended
            - flow-temporary-error
            - pp-otp-error
            - unknown
          example: token-created
        reasons:
          description: |
            Any explanations available to describe the outcome of the most recent action. Empty if no more details are available or needed.
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/missing-parameter'
              - $ref: '#/components/schemas/invalid-parameter'
              - $ref: '#/components/schemas/incompatible-state'
              - $ref: '#/components/schemas/internal-server-error'
              - $ref: '#/components/schemas/service-unavailable'
              - $ref: '#/components/schemas/user-canceled'
              - $ref: '#/components/schemas/expired'
              - $ref: '#/components/schemas/payment-provider-failure'
              - $ref: '#/components/schemas/merchant-failure'
              - $ref: '#/components/schemas/user-invalid'
              - $ref: '#/components/schemas/user-barred'
              - $ref: '#/components/schemas/user-suspended'
              - $ref: '#/components/schemas/user-not-enabled'
              - $ref: '#/components/schemas/rejected'
              - $ref: '#/components/schemas/operation-not-supported'
              - $ref: '#/components/schemas/denied'
              - $ref: '#/components/schemas/unauthorized-flow'
      required:
        - code
        - reasons
    paymentInstrumentToken-flow-mt:
      description: |
        The payment instrument token obtained by the Bango Platform for the partner's end user.

        Only present in the resource when `state` is `succeeded`.
      type: string
      format: uuid
    session-flow-mt:
      title: Identity verification session - MT flow selected
      description: |
        An identity verification session when the MT flow has been selected.
      type: object
      additionalProperties: false
      properties:
        rid:
          $ref: '#/components/schemas/resource-id'
        lastUpdate:
          $ref: '#/components/schemas/lastUpdate'
        partnerSessionId:
          $ref: '#/components/schemas/partnerSessionId'
        paymentProviderId:
          $ref: '#/components/schemas/payment-provider-id'
        private:
          $ref: '#/components/schemas/private'
        shared:
          $ref: '#/components/schemas/identity-session-shared'
        flow:
          $ref: '#/components/schemas/flow-mt'
        state:
          $ref: '#/components/schemas/state-flow-mt'
        otp:
          $ref: '#/components/schemas/otp-flow-mt'
        result:
          $ref: '#/components/schemas/result-flow-mt'
        paymentInstrumentToken:
          $ref: '#/components/schemas/paymentInstrumentToken-flow-mt'
      required:
        - rid
        - lastUpdate
        - flow
        - state
    session:
      title: Identity Verification session
      description: |
        An identity verification session resource.
      oneOf:
        - $ref: '#/components/schemas/session-flow-none'
        - $ref: '#/components/schemas/session-flow-trusted'
        - $ref: '#/components/schemas/session-flow-negotiated'
        - $ref: '#/components/schemas/session-flow-mo'
        - $ref: '#/components/schemas/session-flow-mt'
    CommonErrorResponse:
      type: object
      required:
        - errors
    invalid-json:
      title: invalid-json
      description: The request body is not valid JSON
      type: object
      properties:
        code:
          const: invalid-json
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: The request body is not valid JSON
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/invalid-json
      required:
        - code
        - meta
        - message
    BadRequest:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/invalid-json'
                  - $ref: '#/components/schemas/missing-parameter'
                  - $ref: '#/components/schemas/invalid-parameter'
    invalid-credentials:
      title: invalid-credentials
      description: Authentication error - invalid credentials
      type: object
      properties:
        code:
          const: invalid-credentials
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: The supplied credentials are not valid
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/invalid-credentials
      required:
        - code
        - meta
        - message
    InvalidCredentials:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/invalid-credentials'
    permission-denied:
      title: permission-denied
      description: Authorization error - permission denied
      type: object
      properties:
        code:
          const: permission-denied
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: The client is not permitted to perform this operation
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/permission-denied
      required:
        - code
        - meta
        - message
    PermissionDenied:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/permission-denied'
    not-found:
      title: not-found
      description: Not found or access denied
      type: object
      properties:
        code:
          const: not-found
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: The requested resource was not found
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/not-found
      required:
        - code
        - meta
        - message
    NotFound:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/not-found'
    too-many-requests:
      title: too-many-requests
      description: Too many requests
      type: object
      properties:
        code:
          const: too-many-requests
        meta:
          description: Additional information to help identify the specific error case (empty in this case)
          type: object
        message:
          description: Human-readable message describing the error
          type: string
          example: Request limit reached. Please try again later
        url:
          description: URL to more information about the error type
          type: string
          format: url
          example: https://developer.bango.com/error-codes/too-many-requests
      required:
        - code
        - meta
        - message
    TooManyRequests:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/too-many-requests'
    ServiceUnavailable:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/service-unavailable'
    alias-string:
      title: Alias string
      description: |
        A string that acts as an alternative identifier for another string.

        An alias always has two parts, in this order, separated by a colon:

        - A type
        - A unique ID corresponding to that type

        For example, `my-special-id:adrfhaerhu2`.

        A type may contain only alphanumeric characters and `-` characters, and must not be empty. IDs may be any non-empty string. The maximum length of an alias string, including type and ID, is 1000 bytes (encoded as UTF-8).

        For each partner namespace, the alias must be unique. For example, one namespace can contain aliases `abc:123` and `xyz:123`, but can't contain two aliases both called `abc:123` even if they correspond to different Bango-owned IDs. It's OK for two different namespaces each to contain an alias `abc:123`.
      type: string
      pattern: ^[-a-zA-Z0-9]+:.+$
      maxLength: 1000
      example: my-special-id:adrfhaerhu2
    InternalServerError:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/internal-server-error'
    VERIFY_OTP:
      title: VERIFY_OTP action
      description: |
        A request to check an end user's candidate OTP (typically typed into a merchant form) against the expected OTP associated with the identity verification session.

        The route configuration determines how many attempts a user has to enter an OTP correctly, and how many times the final failed attempt for that OTP will reset the OTP, generating a new set of attempts against a new OTP. The session resource includes the current counts of available retries (attempts at the same OTP) and resets (new OTPs).

        How it works:

        - If the candidate OTP matches the expected OTP, the Bango Platform automatically generates or locates the appropriate payment instrument token and includes it in the session resource returned to the merchant in the response (HTTP 200). In this case, the session state will be `succeeded`.

        - If the candidate OTP does not match the expected OTP, and the user has the right to retry or reset, the Bango Platform returns HTTP 200 with the session resource, and the session state will be `awaiting-user-otp`. The Bango Platform automatically resets the OTP after the last failed retry if any resets are available. The route configuration determines whether the Bango Platform automatically sends the new OTP to the end user (if not, the merchant can use RESEND_OTP to do so).

        - If the candidate OTP does not match the expected OTP, and the user has no retries and no resets available, the Bango Platform returns HTTP 200 with the session resource, and the session state will be `failed`. The merchant must create a new identity verification session to identify the end user.

        HTTP 400 is returned ONLY if the request body does not match the schema defined here. HTTP 400 does NOT mean "the user typed the incorrect OTP".
      type: object
      properties:
        type:
          const: VERIFY_OTP
        payload:
          description: |
            Data needed for the VERIFY_OTP action.
          type: object
          properties:
            account:
              $ref: '#/components/schemas/payment-instrument-account-properties'
            candidate:
              description: |
                The end user's candidate OTP.
              type: string
              minLength: 1
              maxLength: 100
          additionalProperties: false
          required:
            - candidate
      additionalProperties: false
      required:
        - type
        - payload
    RESEND_OTP:
      title: RESEND_OTP action
      description: |
        A request to resend the current OTP to the end user, if it hasn't expired and if route configuration permits.

        If the OTP has expired, or if route configuration does not allow the current OTP to be sent again, this action behaves the same as `RESET_OTP`.
      type: object
      properties:
        type:
          const: RESEND_OTP
        payload:
          description: |
            Data needed for the RESEND_OTP action (none in this case)
          type: object
          properties:
            account:
              $ref: '#/components/schemas/payment-instrument-account-properties'
          additionalProperties: false
      additionalProperties: false
      required:
        - type
        - payload
    RESET_OTP:
      title: RESET_OTP action
      description: |
        A request to reset the OTP (generate a new OTP with a new expiry time) and send it the end user, if any resets are available. The route configuration determines how many times the merchant may reset an OTP within an identity verification session.

        If no resets are available, this action has no effect.
      type: object
      properties:
        type:
          const: RESET_OTP
        payload:
          description: |
            Data needed for the RESET_OTP action (none in this case)
          type: object
          properties:
            account:
              $ref: '#/components/schemas/payment-instrument-account-properties'
          additionalProperties: false
      additionalProperties: false
      required:
        - type
        - payload
    CONFIRM_SESSION_IDENTITY:
      title: CONFIRM_SESSION_IDENTITY action
      description: |
        A request to let the merchant confirm that the end user was properly identified. Used with the MO flow.
      type: object
      properties:
        type:
          const: CONFIRM_SESSION_IDENTITY
        payload:
          description: |
            Data needed for the CONFIRM_SESSION_IDENTITY action.
          type: object
          properties:
            partnerBillingToken:
              description: |
                An optional partner billing token to be used later by the partner in payment transactions.
              type: string
              minLength: 1
              maxLength: 100
          additionalProperties: false
      additionalProperties: false
      required:
        - type
        - payload
    REJECT_SESSION_IDENTITY:
      title: REJECT_SESSION_IDENTITY action
      description: |
        A request to let the merchant reject the tentative identification of an end user, with a reason
      type: object
      properties:
        type:
          const: REJECT_SESSION_IDENTITY
        payload:
          description: |
            Data needed for the REJECT_SESSION_IDENTITY action.
          type: object
          properties:
            code:
              description: |
                A machine-readable code that indicates why the merchant rejected the identity verification session.

                The merchant can use the generic code `rejected` if a more specific code is not available. In this case, it's a good idea to include more details in the `message` field.

                In most cases, the code is reported to the merchant partner in the session resource, in the `result.reasons` array. But note:
                - `adapter-failure` is transformed to `internal-server-error` (because adapters are Bango code, and problems in Bango code are all internal server errors from the merchant's perspective)
                - `merchant-internal-server-error` and `merchant-service-unavailable` are both transformed to `merchant-failure`, with the value of `meta.merchantCode` set appropriately

                **NOTE** List subject to change.
              type: string
              enum:
                - user-canceled
                - expired
                - merchant-internal-server-error
                - merchant-service-unavailable
                - adapter-failure
                - rejected
            message:
              description: |
                An optional human-readable message describing why the merchant rejected the identity verification session.
              type: string
              minLength: 1
              maxLength: 255
          required:
            - code
      required:
        - type
        - payload
    UPDATE_SESSION_DATA:
      title: UPDATE_SESSION_DATA action [ENG-1950]
      description: |
        See [ENG-1950](https://bangonet.atlassian.net/browse/ENG-1950)

        An identity verification session can store:
        - Private merchant partner data, which is not presented to the payment provider
        - Shared data, which is passed between the merchant partner and the payment provider

        This action lets the merchant partner request to update the private data and/or the shared data.
      type: object
      properties:
        type:
          const: UPDATE_SESSION_DATA
        payload:
          type: object
          properties:
            private:
              allOf:
                - $ref: '#/components/schemas/simple-object-patch'
                - $ref: '#/components/schemas/private'
                - title: Patch to private data
                - description: Patch object to modify the merchant-private data in the session
            shared:
              title: Update to data shared to payment provider
              description: |
                Update to the data shared from the merchant partner to the payment provider. Data in `merchantToPaymentProvider` is merged into the existing data.
              type: object
              properties:
                nextAction:
                  $ref: '#/components/schemas/nextAction'
                merchantToPaymentProvider:
                  $ref: '#/components/schemas/merchantToPaymentProvider'
      required:
        - type
        - payload
    Conflict:
      allOf:
        - $ref: '#/components/schemas/CommonErrorResponse'
        - properties:
            errors:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/incompatible-state'
  parameters:
    NamespaceId:
      in: path
      name: nsid
      required: true
      schema:
        $ref: '#/components/schemas/namespace-id'
    ResourceIdOrAlias:
      in: path
      name: ridOrAlias
      required: true
      schema:
        oneOf:
          - $ref: '#/components/schemas/resource-id'
          - $ref: '#/components/schemas/alias-string'
    ResourceId:
      in: path
      name: rid
      required: true
      schema:
        $ref: '#/components/schemas/resource-id'
  responses:
    BadRequestErrorResponse:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BadRequest'
    InvalidCredentialsErrorResponse:
      description: |
        Authentication error - invalid credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InvalidCredentials'
    PermissionDeniedErrorResponse:
      description: |
        User is not authorized for this operation.

        This error occurs when you try to perform an operation on a resource, and you have permission to access the resource - but you don't have permission to perform the operation. For example, you may be authorized to `GET` the resource but not update it.

        (If you try to perform any operation on a resource you're not authorized to access, the API returns a 404 error.)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PermissionDenied'
    NotFoundErrorResponse:
      description: |
        The requested resource was not found or access was denied.

        The API returns an identical error in both scenarios for data privacy reasons: API consumers can't find out anything about resources they aren't authorized to access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/NotFound'
    TooManyRequestsErrorResponse:
      description: |
        Request limit reached. The request was not processed.

        This error occurs when you send too many requests in a short period of time. You should pause before sending further requests.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/TooManyRequests'
    ServiceUnavailableErrorResponse:
      description: Service unavailable
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ServiceUnavailable'
    InternalServerErrorResponse:
      description: Unexpected internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InternalServerError'
    ConflictErrorResponse:
      description: |
        The resource is not in the correct state for the requested operation.

        This error occurs when the current state of a resource means that some operations are not permitted on the resource, and a request is made to perform one of those operations.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Conflict'
