diff --git a/vuepress/docs/.vuepress/config.js b/vuepress/docs/.vuepress/config.js index ef0a3b19..6db0dfcd 100644 --- a/vuepress/docs/.vuepress/config.js +++ b/vuepress/docs/.vuepress/config.js @@ -304,10 +304,35 @@ module.exports = { sidebarDepth: 2 }, { - title: '3PPI/ISP API', + title: 'Thirdparty API', collapsable: false, + path: 'thirdparty/', children: [ - ['3ppi-pisp/', 'Overview'], + { + title: 'API Definitions', + path: 'fspiop/logical-data-model', + collapsable: true + }, + { + title: 'Transaction Patterns', + path: 'thirdparty/transaction-patterns', + collapsable: true, + children: [ + { + title: 'Transaction Patterns Linking', + path: 'thirdparty/transaction-patterns-linking' + }, + { + title: 'Transaction Patterns Transfer', + path: 'thirdparty/transaction-patterns-transfer' + } + ] + }, + { + title: 'Data Models', + path: 'thirdparty/data-models', + collapsable: true + }, ], sidebarDepth: 2 }, diff --git a/vuepress/docs/api/3ppi-pisp/README.md b/vuepress/docs/api/3ppi-pisp/README.md deleted file mode 100644 index dad2448d..00000000 --- a/vuepress/docs/api/3ppi-pisp/README.md +++ /dev/null @@ -1 +0,0 @@ -API specifications goes here \ No newline at end of file diff --git a/vuepress/docs/api/thirdparty/README.md b/vuepress/docs/api/thirdparty/README.md new file mode 100644 index 00000000..e2f39622 --- /dev/null +++ b/vuepress/docs/api/thirdparty/README.md @@ -0,0 +1,41 @@ +# Third Party API + +The Third Party API is an API for non-fund-holding participants to interact over a centralized Mojaloop hub. +Specifically, this API allows Payment Initiation Service Providers (PISPs) to act as a proxy in initiating +payments, while allowing for the strong authentication of users. + +## Terms + +The following terms are commonly used across the Third Party API Documentation + +| **Term** | **Alternative and Related Terms** | **Definition** | **Source** | +| --- | --- | --- | --- | +| **Payment Initiation Service Provider** | PISP, 3rd Party Payment Initiator (3PPI) | Regulated entities like retail banks or third parties, that allow customers to make payments without accessing bank accounts or cards | [PSD2](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32015L2366&qid=1633311418487) | +| **FSP** | Provider, Financial Service Provider (FSP), Payment Service Provider, Digital Financial Services Provider (DFSP) | The entity that provides a digital financial service to an end user (either a consumer, a business, or a government.) In a closed-loop payment system, the Payment System Operator is also the provider. In an open-loop payment system, the providers are the banks or non-banks which participate in that system. | [ITU-T](https://www.itu.int/dms_pub/itu-t/opb/tut/T-TUT-ECOPO-2018-PDF-E.pdf) | +| **User** | End User | An end user that is shared between a PISP and DFSP. Mostly used in the context of a real human being, but this could also be a machine user, or a business for example | +| **Consent** | Account Link | A representation of an agreement between the DFSP, PISP and User | | +| **Auth-Service** | | A service run by the Mojaloop Hub that is responsible for verifying and storing Consents, and verifying transaction request signatures | | + +## API Definitions + +The Third Party API is defined across the following OpenAPI 3.0 files: + +- [Third Party API - PISP](./thirdparty-pisp-v1.0.yaml) +- [Third Party API - DFSP](./thirdparty-dfsp-v1.0.yaml) + +The implementation of these APIs will depend on the role of the participant. PISPs should implement the [Third Party API - PISP](./thirdparty-pisp-v1.0.yaml) +interface in order to request and manage Account Linking operations, and initiate Third Party Transaction Requests. + +DFSPs who wish to support Account Linking operations, and be able to respond to and verify Third Party Transaction Requests should +implement the [Third Party API - DFSP](./thirdparty-dfsp-v1.0.yaml). + +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link + +## Data Models + +The [Data Models Document](./data-models.md) describes in detail the Data Models used in the Third Party API diff --git a/vuepress/docs/api/thirdparty/_sync_docs.sh b/vuepress/docs/api/thirdparty/_sync_docs.sh new file mode 100644 index 00000000..fd92ad48 --- /dev/null +++ b/vuepress/docs/api/thirdparty/_sync_docs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +## +# Synchronises the definition docs from their disparate locations into one place. +# +# The API Spec for the Third Party API is managed by the api-snippets project +## + +set -eu + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +GIT_URL="https://github.com/mojaloop/api-snippets.git" +BRANCH='master' +CLONE_DIR='/tmp/api-snippets' + +rm -rf ${CLONE_DIR} + +git clone -b ${BRANCH} ${GIT_URL} ${CLONE_DIR} + +# API definition, grab from mojaloop/pisp-project +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-dfsp-api.yaml ${DIR}/thirdparty-dfsp-v1.0.yaml +cp ${CLONE_DIR}/thirdparty/openapi3/thirdparty-pisp-api.yaml ${DIR}/thirdparty-pisp-v1.0.yaml diff --git a/vuepress/docs/api/thirdparty/assets/README.md b/vuepress/docs/api/thirdparty/assets/README.md new file mode 100644 index 00000000..8ef0a612 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/README.md @@ -0,0 +1,15 @@ +# thirdparty-api/assets + +Supporting Assets for the Third Party API Specification + + +## Rebuild all Puml -> svg + +For consistent rending of sequence diagrams, we build the .puml sources to .svgs using the following script + +```bash +./_build_plantuml_all.sh +``` + +This also ensures that the sequence diagrams are easily readable inline in markdown documents. + diff --git a/vuepress/docs/api/thirdparty/assets/_build_plantuml_all.sh b/vuepress/docs/api/thirdparty/assets/_build_plantuml_all.sh new file mode 100644 index 00000000..a47edbab --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/_build_plantuml_all.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through repo for plantuml sources +# and exports them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +# Wait for docker to be up +sleep 2 + +for i in $(find ${DIR}/diagrams -name '*.puml'); do + echo "rendering .puml -> .svg for diagram diagram: $i" + ${DIR}/_render_svg.js $i $(echo $i | sed 's/puml/svg/g') +done + +docker stop puml-local diff --git a/vuepress/docs/api/thirdparty/assets/_build_plantuml_diff.sh b/vuepress/docs/api/thirdparty/assets/_build_plantuml_diff.sh new file mode 100644 index 00000000..efe48920 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/_build_plantuml_diff.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PUML_PORT=9999 +export PUML_BASE_URL=http://localhost:${PUML_PORT} + +## +# searches through repo for plantuml sources +# and exports them using `node-plantuml` +## + +trap ctrl_c INT +function ctrl_c() { + echo "exit early - stopping docker" + docker stop puml-local + exit 1 +} + +# run the docker puml server +docker run -d --rm \ + --name puml-local \ + -p ${PUML_PORT}:8080 \ + plantuml/plantuml-server:jetty-v1.2020.21 + +# Wait for docker to be up +sleep 2 + +for i in $(git diff --staged --name-only `find ${DIR}/../docs -name '*.puml'`); do + echo "rendering .puml -> .svg for diagram diagram: $i" + ${DIR}/_render_svg.js $i $(echo $i | sed 's/puml/svg/g') +done + + +git add ./ + +docker stop puml-local diff --git a/vuepress/docs/api/thirdparty/assets/_render_svg.js b/vuepress/docs/api/thirdparty/assets/_render_svg.js new file mode 100644 index 00000000..9e0c8f56 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/_render_svg.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + + +/** + * Uses plantuml server to render a puml to svg + */ + +const fs = require('fs') +const path = require('path') +const util = require('util') +const got = require('got') +const SVGO = require('svgo') +const plantumlEncoder = require('plantuml-encoder') + +const rendererBaseUrl = process.env.PUML_BASE_URL || 'http://www.plantuml.com/plantuml' + +svgo = new SVGO({ + js2svg: { pretty: true, indent: 2 }, + plugins: [ + { removeComments: true }, + ] +}); + +async function main() { + let [_, _script, inputPath, outputPath] = process.argv + + if (!inputPath) { + console.log("usage: ./_render_svg.js []") + process.exit(1) + } + + // If not specified, replace .puml or .plantuml with `.svg` + if (!outputPath) { + outputPath = inputPath.replace('.puml', '.svg') + .replace('.plantuml', '.svg') + } + + const rawPumlContents = fs.readFileSync(inputPath) + const encoded = plantumlEncoder.encode(rawPumlContents.toString()) + const url = path.join(rendererBaseUrl, 'svg', encoded) + let result + try { + result = await got.get(url) + } catch (err) { + console.log('http request failed to render puml with error', err.message) + if (err.message.indexOf('Response code 403') > -1) { + console.log('Note: sometimes the public puml renderer fails when the input diagrams are too large. Try running your own renderer server with docker.') + } + + if (err.message.indexOf('Response code 400') > -1) { + console.log('This could be due to bad syntax in the puml diagram. Url is:') + console.log(url) + } + + process.exit(1) + } + + // Strip comments and prettify svg + // This makes sure that our .svg files are deterministic and diffable + const formatted = await svgo.optimize(result.body) + fs.writeFileSync(outputPath, formatted.data) +} + +main() diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml new file mode 100644 index 00000000..b07cf912 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.puml @@ -0,0 +1,49 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Pre-linking + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +autonumber 1 "PRE-#" +activate App +App -> PISP ++: What DFSPs are available to link with? + + +PISP -> Switch ++: ""GET /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: pispa""\n""FSPIOP-Destination: switch"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> PISP ++: ""PUT /services/THIRD_PARTY_DFSP""\n""FSPIOP-Source: switch""\n""FSPIOP-Destination: pispa""\n\ + ""{""\n\ + "" "serviceProviders": ["" \n\ + "" "dfspa", "dfspb""" \n\ + "" ]"" \n\ + ""}"" +PISP --> Switch: ""200 OK"" + +PISP --> App --: We have dfspa and dfspb\n + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg new file mode 100644 index 00000000..c7ee47f8 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/0-pre-linking.svg @@ -0,0 +1,107 @@ + + + PISP Linking: Pre-linking + + + + Mobile device + + + + PISP + + + + Mojaloop + + + + + + App + + + + PISP + + + + Switch + + + + + PRE-1 + + + What DFSPs are available to link with? + + + + PRE-2 + + + GET /services/THIRD_PARTY_DFSP + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: switch + + + + + PRE-3 + + + 202 Accepted + + + + PRE-4 + + + PUT /services/THIRD_PARTY_DFSP + + + FSPIOP-Source: switch + + + FSPIOP-Destination: pispa + + + { + + + "serviceProviders": [ + + + "dfspa", "dfspb + + + " + + + ] + + + } + + + + + PRE-5 + + + 200 OK + + + + + PRE-6 + + + We have dfspa and dfspb + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.puml new file mode 100644 index 00000000..c719fb2a --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.puml @@ -0,0 +1,85 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Discovery + +box "Mobile device" + participant App +end box + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +... + +note over App, DFSP + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. +end note + +... + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> Switch ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""[""\n\ + "" { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" },""\n\ + "" { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" }""\n\ + ""]"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over App, DFSP + The PISP can now present a list of possible accounts to the user for pairing. +end note + +... + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.svg new file mode 100644 index 00000000..68f6c49c --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/1-discovery.svg @@ -0,0 +1,194 @@ + + + PISP Linking: Discovery + + + + Mobile device + + + + PISP + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + App + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user will be prompted in the PISP App for the unique ID they use with their DFSP, and the type of identifier they use. This could be a an account ALIAS, MSISDN, email address, etc. + + + + DISC-1 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-2 + + + 202 Accepted + + + + DISC-3 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-4 + + + 202 Accepted + + + + DISC-5 + + + PUT /accounts/username1234 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + [ + + + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, + + + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } + + + ] + + + + + DISC-6 + + + 200 OK + + + + DISC-7 + + + PUT /accounts/username1234 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + [ + + + { accountNickname: "Chequing Account", id: "dfspa.username.1234", currency: "ZAR" }, + + + { accountNickname: "Everyday Spend", id: "dfspa.username.5678", currency: "USD" } + + + ] + + + + + DISC-8 + + + 200 OK + + + + + The PISP can now present a list of possible accounts to the user for pairing. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml new file mode 100644 index 00000000..8d52071b --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.puml @@ -0,0 +1,119 @@ +@startuml + + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Request consent (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the consentRequest validity + + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" + +note over PISP, DFSP + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). +end note + +deactivate DFSP + +Switch -> PISP: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ +""{""\n\ + "" authChannels: [ "OTP" ], ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg new file mode 100644 index 00000000..ad65ece6 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-otp.svg @@ -0,0 +1,294 @@ + + + PISP Linking: Request consent (OTP) + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + REQ-5 + + + Verify the consentRequest validity + + + + REQ-6 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + authChannels: [ "OTP" ], + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-7 + + + 200 OK + + + + + Here, the DFSP sends an OTP directly to the user (e.g., via SMS). + + + + REQ-8 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + authChannels: [ "OTP" ], + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-9 + + + 200 OK + + + + + At this point, the PISP knows that the OTP authChannel is in use and the PISP App should prompt the user to provide the OTP. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml new file mode 100644 index 00000000..de404fc3 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.puml @@ -0,0 +1,118 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +title PISP Linking: Request consent (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "REQ-#" + +activate PISP + +... + +note over PISP, DFSP + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. +end note + +... + +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234", ""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ + "" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" + +DFSP -> DFSP: Verify the consentRequest validity +DFSP -> DFSP: In this case, DFSP chooses to use the Web channel, \n and adds the PISP's callback uri to an allow-list +deactivate Switch + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + "" {""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "Web" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + "" authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch + +note over PISP, DFSP + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided ""authUri"". +end note + + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg new file mode 100644 index 00000000..ecffd688 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/2-request-consent-web.svg @@ -0,0 +1,311 @@ + + + PISP Linking: Request consent (Web) + + + + Mojaloop + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + + + + The user initiated some sort of account linking by choosing the appropriate DFSP from a screen inside the PISP application. + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + REQ-5 + + + Verify the consentRequest validity + + + + REQ-6 + + + In this case, DFSP chooses to use the Web channel, + + + and adds the PISP's callback uri to an allow-list + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web" ], + + + callbackUri: "pisp-app://callback... + + + " + + + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" + + + } + + + + + REQ-8 + + + 200 OK + + + + REQ-9 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "Web" ], + + + callbackUri: "pisp-app://callback... + + + " + + + authUri: "dfspa.com/authorize?consentRequestId=11111111-0000-0000-0000-000000000000" + + + } + + + + + REQ-10 + + + 200 OK + + + + + At this point, the PISP knows that the Web authChannel is in use and the PISP App should redirect the user to the provided + + + authUri + + + . + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml new file mode 100644 index 00000000..2fdb17e5 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.puml @@ -0,0 +1,62 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (OTP) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +... + +note over PISP, DFSP + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg new file mode 100644 index 00000000..3372bda1 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-otp.svg @@ -0,0 +1,116 @@ + + + PISP Linking: Authentication (OTP) + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + Here the user provides the OTP sent directly to them by the DFSP into the PISP App. It's then used as the secret to prove to the DFSP that the user trusts the PISP. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + Verify the OTP is correct. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml new file mode 100644 index 00000000..9d05ec44 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.puml @@ -0,0 +1,45 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Third-party FIDO registration) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "3P-FIDO-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. +end note + +... + +autonumber 1 "AUTH-#" + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg new file mode 100644 index 00000000..32fdc652 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-third-party-fido.svg @@ -0,0 +1,50 @@ + + + PISP Linking: Authentication (Third-party FIDO registration) + + + + Mojaloop + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + Here the user goes through the web authentication process with their DFSP. + + + The end result is a redirect back to the PISP with a special URL parameter indicating to the PISP that it should wait to be notified about a credential. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml new file mode 100644 index 00000000..f31a9ed5 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.puml @@ -0,0 +1,65 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication (Web) + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "WEB-AUTH-#" + +... + +note over PISP, DFSP + Here the user goes through the web authentication process with their DFSP. + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. +end note + +... + +autonumber 1 "AUTH-#" + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the auth token is correct. + +note over PISP, DFSP + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg new file mode 100644 index 00000000..8ed74081 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/3-authentication-web.svg @@ -0,0 +1,119 @@ + + + PISP Linking: Authentication (Web) + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + Here the user goes through the web authentication process with their DFSP. + + + The end result is a redirect back to the PISP with a special URL parameter with a secret provided by the DFSP. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<SECRET>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<SECRET>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + Verify the auth token is correct. + + + + + At this point, the DFSP believes that the User is their customer and that User trusts the PISP. This means that the DFSP can continue by granting consent. + + + Note that the DFSP never "responds" to the Consent Request itself. Instead, it will create a Consent resource in the Grant phase. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml new file mode 100644 index 00000000..e0ede15d --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.puml @@ -0,0 +1,64 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Grant consent + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +DFSP -> Switch ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" +Switch --> DFSP: ""202 Accepted"" +deactivate DFSP + +Switch -> PISP ++: ""POST /consents""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000",""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + ""}"" + +PISP --> Switch: ""202 Accepted"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg new file mode 100644 index 00000000..60e2e734 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/4-grant-consent.svg @@ -0,0 +1,134 @@ + + + + Mojaloop + + + PISP Linking: Grant consent + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + GRANT-1 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + consentId: "22222222-0000-0000-0000-000000000000", + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + } + + + + + GRANT-2 + + + 202 Accepted + + + + GRANT-3 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + consentId: "22222222-0000-0000-0000-000000000000", + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + } + + + + + GRANT-4 + + + 202 Accepted + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml new file mode 100644 index 00000000..b7cd8fe0 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.puml @@ -0,0 +1,219 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 0 "CRED-#" + +... + +note over PISP, DFSP + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. + + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + See https://webauthn.guide/#authentication for more information on this object +end note + +... + +PISP -> Switch ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + + +Switch -> DFSP ++: ""PUT /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: ""202 Accepted"" + + +rnote over DFSP + 1. DFSP checks the signed challenge against the derived challenge from the scopes + + If the DFSP opts to use the hub-hosted Auth-Service it then: + 1. Registers the consent with the Auth Service ""POST /consents"" + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains + ""Consent.credential.status"" of ""VERIFIED"", for each scope in the + Consent, the DFSP creates a ""CredentialScope"" else, if it recieves + a `PUT /consents/{id}/error` callback, it knows that the Consent is + invalid, and can propagate the error back to the PISP + +end note + + +DFSP -> Switch: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {""\n\ + "" consentId: "22222222-0000-0000-0000-000000000000"""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000"""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ],""\n\ + "" }""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "PENDING",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" + +Switch --> DFSP: "202 Accepted" + + +Switch -> Auth: ""POST /consents"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: central-auth""\n\ +"" {...}"" + +Auth --> Switch: "202 Accepted" + + +rnote over Auth + The Auth Service checks the signature against the challenge +end note + +rnote over Auth + The auth service is now the authoritative source for the Consent object. + + It must register the consentId with the ALS + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent +end note + +Auth -> ALS: ""POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +ALS --> Auth: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the Consents oracle +end note + +ALS -> Auth: ""PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: central-auth""\n\ +"" {""\n\ +"" fspId: "central-auth",""\n\ +"" }"" +Auth --> ALS: ""200 OK"" + +rnote over Auth #LightGray + The auth service now informs the DFSP that the credential is valid +end note + + +Auth -> Switch: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000"""\n\ + "" status: "ISSUED",""\n\ + "" scopes: [""\n\ + "" {""\n\ + "" accountId: "dfsp.username.1234",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" {""\n\ + "" accountId: "dfsp.username.5678",""\n\ + "" actions: [ "accounts.transfer", "accounts.getBalance" ],""\n\ + "" },""\n\ + "" ],""\n\ + "" credential: { ""\n\ + "" credentialType: "FIDO",""\n\ + "" status: "VERIFIED",""\n\ + "" fidoPayload: { ""\n\ + "" id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", "" \n\ + "" response: { ""\n\ + "" "" authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==",\n\ + "" "" clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...",\n\ + "" "" signature: "MEUCIDcJRBu5aOLJVc..."\n\ + "" } ""\n\ + "" } ""\n\ + "" }""\n\ +"" }"" +Switch --> Auth: "200 OK" + +Switch -> DFSP: ""PUT /consents/22222222-0000-0000-0000-000000000000"" \n\ +"" FSIOP-Source: central-auth""\n\ +"" FSPIOP-Destination: dfspa""\n\ +"" {...}"" + +DFSP --> Switch: "200 OK" + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg new file mode 100644 index 00000000..8a792580 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5a-credential-registration.svg @@ -0,0 +1,577 @@ + + + + Mojaloop + + + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Thirdparty-API-Adapter + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + The PISP uses the FIDO registration flow to generate a new keypair and sign the challenge, relying on the user performing an "unlock action" on their mobile device. + + + The PISP uses the PublicKeyCredential as the fidoPayload for the credential, which can be understood by the Auth Service and DFSP + + + See https://webauthn.guide/#authentication for more information on this object + + + + CRED-0 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "PENDING", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-1 + + + 202 Accepted + + + + CRED-2 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + {...} + + + + + CRED-3 + + + 202 Accepted + + + + 1. DFSP checks the signed challenge against the derived challenge from the scopes + + + If the DFSP opts to use the hub-hosted Auth-Service it then: + + + 1. Registers the consent with the Auth Service + + + POST /consents + + + 2. If the DFSP recieves a `PUT /consents/{id}` and the callback contains + + + Consent.credential.status + + + of + + + VERIFIED + + + , for each scope in the + + + Consent, the DFSP creates a + + + CredentialScope + + + else, if it recieves + + + a `PUT /consents/{id}/error` callback, it knows that the Consent is + + + invalid, and can propagate the error back to the PISP + + + + CRED-4 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + consentId: "22222222-0000-0000-0000-000000000000 + + + " + + + consentRequestId: "11111111-0000-0000-0000-000000000000 + + + " + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ], + + + } + + + }, + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "PENDING", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-5 + + + "202 Accepted" + + + + CRED-6 + + + POST /consents + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + {...} + + + + + CRED-7 + + + "202 Accepted" + + + + The Auth Service checks the signature against the challenge + + + + The auth service is now the authoritative source for the Consent object. + + + It must register the consentId with the ALS + + + - `Consent` - to allow for `GET /consent/{ID}` calls etc. Will point to the fspId of the Auth Service responsible for the Consent + + + + CRED-8 + + + POST /participants/CONSENTS/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + { + + + fspId: "central-auth", + + + } + + + + + CRED-9 + + + 202 Accepted + + + + ALS registers a new entry in the Consents oracle + + + + CRED-10 + + + PUT /participants/CONSENTS/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: account-lookup-service + + + FSIOP-Destination: central-auth + + + { + + + fspId: "central-auth", + + + } + + + + + CRED-11 + + + 200 OK + + + + The auth service now informs the DFSP that the credential is valid + + + + CRED-12 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000 + + + " + + + status: "ISSUED", + + + scopes: [ + + + { + + + accountId: "dfsp.username.1234", + + + actions: [ "accounts.transfer", "accounts.getBalance" ], + + + }, + + + { + + + accountId: "dfsp.username.5678", + + + actions: [ "accounts.transfer", "accounts.getBalance" ], + + + }, + + + ], + + + credential: { + + + credentialType: "FIDO", + + + status: "VERIFIED", + + + fidoPayload: { + + + id: "45c-TkfkjQovQeAWmOy-RLBHEJ_e4jYzQYgD8VdbkePgM5d98BaAadadNYrknxgH0jQEON8zBydLgh1EqoC9DA", + + + response: { + + + authenticatorData: "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MBAAAACA==", + + + clientDataJSON: "eyJ0eXBlIjoid2ViYXV0aG4...", + + + signature: "MEUCIDcJRBu5aOLJVc..." + + + } + + + } + + + } + + + } + + + + + CRED-13 + + + "200 OK" + + + + CRED-14 + + + PUT /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + {...} + + + + + CRED-15 + + + "200 OK" + + + + DFSP is now satisfied that the Consent registered by the PISP is valid. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml new file mode 100644 index 00000000..791a929d --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.puml @@ -0,0 +1,97 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Credential registration (verification) + +participant "PISP" as PISP + +box "Mojaloop" + participant "Switch" as Switch + participant "Account Lookup Service" as ALS +end box + +participant "DFSP" as DFSP + +autonumber 16 "CRED-#" + +... + + +rnote over DFSP + DFSP is now satisfied that the Consent registered by the PISP is valid, + and now proceeds to register with the ALS: + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + ALS +end note + +loop for each scope in ""Consents.scopes"" + +DFSP -> ALS: ""POST /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +ALS --> DFSP: ""202 Accepted"" + +rnote over ALS #LightGray + ALS registers a new entry in the THIRD_PARTY_LINK oracle +end note + +ALS -> DFSP: ""PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678"" \n\ +"" FSIOP-Source: account-lookup-service""\n\ +"" FSIOP-Destination: dfspa""\n\ +"" {""\n\ +"" fspId: "dfspa",""\n\ +"" }"" +DFSP --> ALS: ""200 OK"" +end + + +rnote over DFSP + Now that the Credentials are verified and registered with the Auth Service, + the DFSP can update the PISP with the final status +end note + +DFSP -> Switch: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +DFSP --> Switch: ""200 OK"" + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSPIOP-Destination: pispa""\n\ +"" Content-Type: application/merge-patch+json""\n\ +"" {""\n\ + "" credential: {""\n\ + "" **status: "VERIFIED", //this is new!**""\n\ + "" }""\n\ +"" }"" +PISP --> Switch: ""200 OK"" + + +note over PISP, DFSP + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service +end note + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg new file mode 100644 index 00000000..54ba4470 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/5b-finalize_consent.svg @@ -0,0 +1,215 @@ + + + + Mojaloop + + + PISP Linking: Credential registration (verification) + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + Account Lookup Service + + + + DFSP + + + + DFSP is now satisfied that the Consent registered by the PISP is valid, + + + and now proceeds to register with the ALS: + + + - `THIRD_PARTY_LINK` (optional - for routing of funds to a Third Party Link) + + + ALS + + + + + loop + + + [for each scope in + + + Consents.scopes + + + ] + + + + CRED-16 + + + POST /participants/THIRD_PARTY_LINK/dfsp.username.5678 + + + FSIOP-Source: dfspa + + + { + + + fspId: "dfspa", + + + } + + + + + CRED-17 + + + 202 Accepted + + + + ALS registers a new entry in the THIRD_PARTY_LINK oracle + + + + CRED-18 + + + PUT /participants/THIRD_PARTY_LINK/dfsp.username.5678 + + + FSIOP-Source: account-lookup-service + + + FSIOP-Destination: dfspa + + + { + + + fspId: "dfspa", + + + } + + + + + CRED-19 + + + 200 OK + + + + Now that the Credentials are verified and registered with the Auth Service, + + + the DFSP can update the PISP with the final status + + + + CRED-20 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + Content-Type: application/merge-patch+json + + + { + + + credential: { + + + status: "VERIFIED", //this is new! + + + } + + + } + + + + + CRED-21 + + + 200 OK + + + + CRED-22 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + Content-Type: application/merge-patch+json + + + { + + + credential: { + + + status: "VERIFIED", //this is new! + + + } + + + } + + + + + CRED-23 + + + 200 OK + + + + + Now we have a new identifier that the PISP can use to initiate transactions, a registered credential, and that credential is stored in the auth-service + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml new file mode 100644 index 00000000..4c2ff1b5 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-A-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Mark the ""Consent"" object as "REVOKED" + +DFSP -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: dfspa""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg new file mode 100644 index 00000000..14dabe21 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg @@ -0,0 +1,172 @@ + + + + Mojaloop + + + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + + + Consent + + + object. + + + + UNLINK-A-1 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + UNLINK-A-2 + + + 202 Accepted + + + + UNLINK-A-3 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-A-4 + + + 202 Accepted + + + + UNLINK-A-5 + + + Mark the + + + Consent + + + object as "REVOKED" + + + + UNLINK-A-6 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-A-7 + + + 200 OK + + + + UNLINK-A-8 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + } + + + + + UNLINK-A-9 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml new file mode 100644 index 00000000..914dc770 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.puml @@ -0,0 +1,105 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +!pragma teoz true + +title PISP Linking: Unlinking + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "UNLINK-B-#" + +activate PISP + +... + +note over PISP, DFSP + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the ""Consent"" object. +end note + +... + +PISP -> Switch ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: pispa""\n\ +"" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> ALS: ""GET /participants/CONSENT/22222222-0000-0000-0000-000000000000"" +ALS --> Switch: ""200 OK""\n\ +"" { "fspId": "central-auth" }"" + +rnote over Switch #LightGray + Hub has determined that 'central-auth- is responsible for ""Consent"" 22222222-0000-0000-0000-000000000000 +end note + +Switch -> Auth ++: ""DELETE /consents/22222222-0000-0000-0000-000000000000"" +Auth --> Switch: ""202 Accepted"" +deactivate Switch + +Auth -> Auth: Mark the ""Consent"" object as "REVOKED" + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> PISP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: pispa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +PISP --> Switch: ""200 OK"" + + +rnote over Auth #LightGray + Auth Service must also inform the DFSP of the updated status +end note + +Auth -> Switch ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +Switch --> Auth: ""200 OK"" +deactivate Auth + +Switch -> DFSP ++: ""PATCH /consents/22222222-0000-0000-0000-000000000000""\n\ +"" FSIOP-Source: central-auth""\n\ +"" FSIOP-Destination: dfspa""\n\ +""{ ""\n\ +"" status: "REVOKED",""\n\ +"" revokedAt: "2020-06-15T13:00:00.000"""\n\ +""}"" +DFSP --> Switch: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg new file mode 100644 index 00000000..bb3c5019 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/6b-unlinking-hub-hosted.svg @@ -0,0 +1,298 @@ + + + + Mojaloop + + + PISP Linking: Unlinking + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + In this scenario there is no Hub-hosted Auth Service. The DFSP is the authority on the + + + Consent + + + object. + + + + UNLINK-B-1 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + UNLINK-B-2 + + + 202 Accepted + + + + UNLINK-B-3 + + + GET /participants/CONSENT/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-B-4 + + + 200 OK + + + { "fspId": "central-auth" } + + + + Hub has determined that 'central-auth- is responsible for + + + Consent + + + 22222222-0000-0000-0000-000000000000 + + + + UNLINK-B-5 + + + DELETE /consents/22222222-0000-0000-0000-000000000000 + + + + + UNLINK-B-6 + + + 202 Accepted + + + + UNLINK-B-7 + + + Mark the + + + Consent + + + object as "REVOKED" + + + + UNLINK-B-8 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-9 + + + 200 OK + + + + UNLINK-B-10 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: pispa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-11 + + + 200 OK + + + + Auth Service must also inform the DFSP of the updated status + + + + UNLINK-B-12 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: dfspa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-13 + + + 200 OK + + + + UNLINK-B-14 + + + PATCH /consents/22222222-0000-0000-0000-000000000000 + + + FSIOP-Source: central-auth + + + FSIOP-Destination: dfspa + + + { + + + status: "REVOKED", + + + revokedAt: "2020-06-15T13:00:00.000 + + + " + + + } + + + + + UNLINK-B-15 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml new file mode 100644 index 00000000..bf5d76ca --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.puml @@ -0,0 +1,79 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Discovery error case + +box "PISP" + participant PISP +end box + +box "Mojaloop" + participant Switch +end box + +participant DFSP + +autonumber 1 "DISC-#" +activate PISP + +PISP -> Switch ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""GET /accounts/username1234""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Lookup a user for **username1234** +DFSP -> DFSP: No user found + +DFSP -> Switch ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /accounts/username1234/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6205", ""\n\ + "" errorDescription: "No accounts found" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +... + +note over Switch + The PISP can now show error message and user can try again with another username or different DFSP. +end note + +... + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg new file mode 100644 index 00000000..d3d18465 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/1-discovery-error.svg @@ -0,0 +1,182 @@ + + + PISP Linking: Discovery error case + + + + PISP + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + DISC-1 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-2 + + + 202 Accepted + + + + DISC-3 + + + GET /accounts/username1234 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + + + DISC-4 + + + 202 Accepted + + + + DISC-5 + + + Lookup a user for + + + username1234 + + + + DISC-6 + + + No user found + + + + DISC-7 + + + PUT /accounts/username1234/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6205", + + + errorDescription: "No accounts found" + + + } + + + } + + + + + DISC-8 + + + 200 OK + + + + DISC-9 + + + PUT /accounts/username1234/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6205", + + + errorDescription: "No accounts found" + + + } + + + } + + + + + DISC-10 + + + 200 OK + + + + + The PISP can now show error message and user can try again with another username or different DFSP. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml new file mode 100644 index 00000000..e3cbf456 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.puml @@ -0,0 +1,162 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title **PISP Linking: consentRequest error cases** + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +== NO_SUPPORTED_SCOPE_ACTIONS == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.91011",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "pisp-app://callback..."""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The PISP requested permissions \nfor accountId dfsp.username.91011 which \n isn't owned by username1234 + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6101", ""\n\ + "" errorDescription: "Unsupported scopes were requested" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +== UNTRUSTED_CALLBACK_URI == + +autonumber 1 "REQ-#" +PISP -> Switch ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234", ""\n\ + "" scopes: [ ""\n\ + "" { **accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""POST /consentRequests""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +""{""\n\ + "" consentRequestId: "11111111-0000-0000-0000-000000000000",""\n\ + "" userId: "username1234",""\n\ + "" scopes: [ ""\n\ + "" { accountId: "dfsp.username.1234",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" { accountId: "dfsp.username.5678",""\n\ + "" actions: [ "ACCOUNTS_TRANSFER" ] },""\n\ + "" ],""\n\ + "" authChannels: [ "WEB", "OTP" ],""\n\ + "" callbackUri: "http://phishing.com"""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +autonumber 1 "DFSP-#" +DFSP -> DFSP: The callbackUri uses http scheme \ninstead of https. Reject the consentRequest + +autonumber 5 "REQ-#" +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6204", ""\n\ + "" errorDescription: "Bad callbackUri" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg new file mode 100644 index 00000000..50cacb14 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/2-request-consent-error.svg @@ -0,0 +1,455 @@ + + + PISP Linking: consentRequest error cases + + + + Mojaloop + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + NO_SUPPORTED_SCOPE_ACTIONS + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.91011", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.91011", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "pisp-app://callback... + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + DFSP-1 + + + The PISP requested permissions + + + for accountId dfsp.username.91011 which + + + isn't owned by username1234 + + + + REQ-5 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6101", + + + errorDescription: "Unsupported scopes were requested" + + + } + + + } + + + + + REQ-6 + + + 200 OK + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6101", + + + errorDescription: "Unsupported scopes were requested" + + + } + + + } + + + + + REQ-8 + + + 200 OK + + + + + + UNTRUSTED_CALLBACK_URI + + + + REQ-1 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { **accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "http://phishing.com + + + " + + + } + + + + + REQ-2 + + + 202 Accepted + + + + REQ-3 + + + POST /consentRequests + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + consentRequestId: "11111111-0000-0000-0000-000000000000", + + + userId: "username1234", + + + scopes: [ + + + { accountId: "dfsp.username.1234", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + { accountId: "dfsp.username.5678", + + + actions: [ "ACCOUNTS_TRANSFER" ] }, + + + ], + + + authChannels: [ "WEB", "OTP" ], + + + callbackUri: "http://phishing.com + + + " + + + } + + + + + REQ-4 + + + 202 Accepted + + + + DFSP-1 + + + The callbackUri uses http scheme + + + instead of https. Reject the consentRequest + + + + REQ-5 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6204", + + + errorDescription: "Bad callbackUri" + + + } + + + } + + + + + REQ-6 + + + 200 OK + + + + REQ-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6204", + + + errorDescription: "Bad callbackUri" + + + } + + + } + + + + + REQ-8 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml new file mode 100644 index 00000000..c8856001 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.puml @@ -0,0 +1,87 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISP Linking: Authentication Invalid authToken + +participant "PISP" as PISP + +box "Mojaloop" + participant Switch +end box + +participant "DFSP" as DFSP + +autonumber 1 "AUTH-#" + +== Failure case == + +... + +note over PISP, DFSP + The user enters an incorrect OTP for authentication. +end note + +... + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: The OTP is incorrect. + +note over PISP, DFSP + We respond with an error that the OTP is incorrect so the PISP can inform the user. +end note + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "6203", ""\n\ + "" errorDescription: "Invalid authentication token" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg new file mode 100644 index 00000000..4320e199 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg @@ -0,0 +1,197 @@ + + + PISP Linking: Authentication Invalid authToken + + + + Mojaloop + + + + + + + + + + + + + + + + + + PISP + + + + Switch + + + + DFSP + + + + + + + Failure case + + + + + The user enters an incorrect OTP for authentication. + + + + AUTH-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-2 + + + 202 Accepted + + + + AUTH-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + AUTH-4 + + + 202 Accepted + + + + AUTH-5 + + + The OTP is incorrect. + + + + + We respond with an error that the OTP is incorrect so the PISP can inform the user. + + + + AUTH-6 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6203", + + + errorDescription: "Invalid authentication token" + + + } + + + } + + + + + AUTH-7 + + + 200 OK + + + + AUTH-8 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "6203", + + + errorDescription: "Invalid authentication token" + + + } + + + } + + + + + AUTH-9 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml new file mode 100644 index 00000000..c9e4f772 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + + +!pragma teoz true + +title PISP Linking: Grant consent scope retrieval error + +participant "PISP" as PISP + +box "Mojaloop" + participant "Thirdparty-API-Adapter" as Switch + participant "Account Lookup Service" as ALS + participant "Auth Service" as Auth +end box + +participant "DFSP" as DFSP + +autonumber 1 "GRANT-#" + +== Failure case == + +PISP -> Switch ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +Switch --> PISP: ""202 Accepted"" +deactivate PISP + +Switch -> DFSP ++: ""PATCH /consentRequests/11111111-0000-0000-0000-000000000000""\n\ + "" FSIOP-Source: pispa""\n\ + "" FSIOP-Destination: dfspa""\n\ +"" {""\n\ + "" authToken: "" ""\n\ + ""}"" +DFSP --> Switch: ""202 Accepted"" +deactivate Switch + +DFSP -> DFSP: Verify the OTP is correct. + +DFSP -> DFSP: Unable to fetch stored scopes + +DFSP -> Switch ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +Switch --> DFSP: ""200 OK"" +deactivate DFSP + +Switch -> PISP ++: ""PUT /consentRequests/11111111-0000-0000-0000-000000000000/error""\n\ + "" FSIOP-Source: dfspa""\n\ + "" FSIOP-Destination: pispa""\n\ + ""{""\n\ + "" errorInformation : { ""\n\ + "" errorCode: "7207", ""\n\ + "" errorDescription: "FSP failed retrieve scopes for consent request" ""\n\ + "" } ""\n\ + ""}"" +PISP --> Switch: ""200 OK"" +deactivate Switch +deactivate PISP + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg new file mode 100644 index 00000000..cc0b292e --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/linking/error_scenarios/4-grant-consent-scope-error.svg @@ -0,0 +1,191 @@ + + + + Mojaloop + + + PISP Linking: Grant consent scope retrieval error + + + + + + + + PISP + + + + Thirdparty-API-Adapter + + + + Account Lookup Service + + + + Auth Service + + + + DFSP + + + + + + Failure case + + + + GRANT-1 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + GRANT-2 + + + 202 Accepted + + + + GRANT-3 + + + PATCH /consentRequests/11111111-0000-0000-0000-000000000000 + + + FSIOP-Source: pispa + + + FSIOP-Destination: dfspa + + + { + + + authToken: "<OTP>" + + + } + + + + + GRANT-4 + + + 202 Accepted + + + + GRANT-5 + + + Verify the OTP is correct. + + + + GRANT-6 + + + Unable to fetch stored scopes + + + + GRANT-7 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "7207", + + + errorDescription: "FSP failed retrieve scopes for consent request" + + + } + + + } + + + + + GRANT-8 + + + 200 OK + + + + GRANT-9 + + + PUT /consentRequests/11111111-0000-0000-0000-000000000000/error + + + FSIOP-Source: dfspa + + + FSIOP-Destination: pispa + + + { + + + errorInformation : { + + + errorCode: "7207", + + + errorDescription: "FSP failed retrieve scopes for consent request" + + + } + + + } + + + + + GRANT-10 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml new file mode 100644 index 00000000..4cbf4dc6 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.puml @@ -0,0 +1,72 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.1 Discovery + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + + +== Discovery (Lookup) == +rnote right of D1 #Light +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +end note +D1 -> S: ""GET /parties/MSISDN/+4412345678"" +S --> D1: ""202 Accepted"" + +... ALS lookup flow not shown here ... + +rnote over S #Light +**""GET /parties/MSISDN/+4412345678""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspb"" +end note +S -> D3: ""GET /parties/MSISDN/+4412345678"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /parties/MSISDN/+4412345678""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: pispa"" +{ + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + party: { + partyIdInfo: { + partyIdType: "MSISDN", + partyIdentifier: "+4412345678", + fspId: 'dfspb", + }, + name: "Bhavesh S.", + } +} +end note +D3 -> S: ""PUT /parties/MSISDN/+4412345678"" +S --> D3: ""200 OK"" +S -> D1: ""PUT /parties/MSISDN/+4412345678"" +D1 --> S: ""200 OK"" + +... PISP confirms payee party with their user ... + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg new file mode 100644 index 00000000..3517b835 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-1-discovery.svg @@ -0,0 +1,156 @@ + + + Transfer: 1.1 Discovery + + + + PISP + + + + Mojaloop + + + + DFSP B + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP B + + + (Payee) + + + + + + Discovery (Lookup) + + + + GET /parties/MSISDN/+4412345678 + + + FSPIOP-Source: pispa + + + + GET /parties/MSISDN/+4412345678 + + + + + 202 Accepted + + + ALS lookup flow not shown here + + + + GET /parties/MSISDN/+4412345678 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspb + + + + GET /parties/MSISDN/+4412345678 + + + + + 202 Accepted + + + + PUT /parties/MSISDN/+4412345678 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: pispa + + + { + + + partyIdType: "MSISDN", + + + partyIdentifier: "+4412345678", + + + party: { + + + partyIdInfo: { + + + partyIdType: "MSISDN", + + + partyIdentifier: "+4412345678", + + + fspId: 'dfspb", + + + }, + + + name: "Bhavesh S.", + + + } + + + } + + + + PUT /parties/MSISDN/+4412345678 + + + + + 200 OK + + + + PUT /parties/MSISDN/+4412345678 + + + + + 200 OK + + + PISP confirms payee party with their user + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml new file mode 100644 index 00000000..21250e52 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.puml @@ -0,0 +1,86 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.1 Agreement + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" +D2 -> D2: Lookup the consent for this ""payer"", verify that they exist, and consent \nis granted with a valid credential +D2 -> D2: Store a referece to the ""consentId"" with the ""transactionRequestId"" +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg new file mode 100644 index 00000000..4c898f7e --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-1-agreement.svg @@ -0,0 +1,224 @@ + + + Transfer: 1.2.1 Agreement + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + Lookup the consent for this + + + payer + + + , verify that they exist, and consent + + + is granted with a valid credential + + + + Store a referece to the + + + consentId + + + with the + + + transactionRequestId + + + + Generate a unique transactionId for this transaction request: + + + 11111111-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "RECEIVED" + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml new file mode 100644 index 00000000..798e8224 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.puml @@ -0,0 +1,150 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.2 Authorization + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +rnote left of D2 #Light +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "123456789", + "fspId": "dfspa" + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +rnote left of D2 #Light +**""PUT /quotes/22222222-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "transferAmount": { + "amount": "100", + "currency": "USD" + }, + "payeeReceiveAmount": { + "amount": "99", + "currency": "USD" + }, + "payeeFspFee": { + "amount": "1", + "currency": "USD" + }, + "expiration": "2020-06-15T12:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note left of D2 + DFSP A has the quote, they can now ask + the PISP for authorization +end note + +D2 -> D2: Generate a UUID for the authorization Request:\n""33333333-0000-0000-0000-000000000000"" +D2 -> D2: Derive the challenge based \non ""PUT /quotes/{ID}"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/authorizations""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "challenge": """", + "transferAmount": {"amount": "100", "currency": "USD"}, + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + "fees": {"amount": "1", "currency": "USD"}, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T12:00:00.000", +} +end note +D2 -> S: ""POST /thirdpartyRequests/authorizations"" +S --> D2: ""202 Accepted"" +S -> D1: ""POST /thirdpartyRequests/authorizations"" +D1 --> S: ""202 Accepted"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg new file mode 100644 index 00000000..a483f863 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-2-authorization.svg @@ -0,0 +1,396 @@ + + + Transfer: 1.2.2 Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + + POST /quotes + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "quoteId": "22222222-0000-0000-0000-000000000000", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "personalInfo": { + + + "complexName": { + + + "firstName": "Ayesha", + + + "lastName": "Takia" + + + } + + + }, + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "123456789", + + + "fspId": "dfspa" + + + }, + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "note": "quote note" + + + } + + + + POST /quotes + + + + + 202 Accepted + + + + POST /quotes + + + + + 202 Accepted + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "transferAmount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "payeeReceiveAmount": { + + + "amount": "99", + + + "currency": "USD" + + + }, + + + "payeeFspFee": { + + + "amount": "1", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T12:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /quotes/22222222-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + DFSP A has the quote, they can now ask + + + the PISP for authorization + + + + Generate a UUID for the authorization Request: + + + 33333333-0000-0000-0000-000000000000 + + + + Derive the challenge based + + + on + + + PUT /quotes/{ID} + + + + POST /thirdpartyRequests/authorizations + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "authorizationRequestId": "33333333-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "transferAmount": {"amount": "100", "currency": "USD"}, + + + "payeeReceiveAmount": {"amount": "99", "currency": "USD"}, + + + "fees": {"amount": "1", "currency": "USD"}, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T12:00:00.000", + + + } + + + + POST /thirdpartyRequests/authorizations + + + + + 202 Accepted + + + + POST /thirdpartyRequests/authorizations + + + + + 202 Accepted + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml new file mode 100644 index 00000000..01205b80 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.puml @@ -0,0 +1,76 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Rejected Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + + + User rejects the terms of the transcationRequest +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "REJECTED" +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" + +note over D2 + User has rejected the transaction request. +end note + +rnote over D2 #Light +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "REJECTED", + "transactionId": "11111111-0000-0000-0000-000000000000", +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can inform the user the transaction did not proceed +end note + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg new file mode 100644 index 00000000..0187f0d3 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-rejected-authorization.svg @@ -0,0 +1,165 @@ + + + Transfer: 1.2.3 Rejected Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + User rejects the terms of the transcationRequest + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "REJECTED" + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + + User has rejected the transaction request. + + + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "REJECTED", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + } + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + PISP can inform the user the transaction did not proceed + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml new file mode 100644 index 00000000..90b1b7b8 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.puml @@ -0,0 +1,74 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization FIDO + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the terms with the user. + + If the user agrees to the terms, the PISP + uses the FIDO API on the user's device to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg new file mode 100644 index 00000000..789519f6 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg @@ -0,0 +1,187 @@ + + + Transfer: 1.2.3 Signed Authorization FIDO + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the terms with the user. + + + If the user agrees to the terms, the PISP + + + uses the FIDO API on the user's device to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + + DFSP has the signed challenge. + + + It now needs to ask the Auth-Service to verify + + + the signed challenge. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml new file mode 100644 index 00000000..28d5c723 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.puml @@ -0,0 +1,63 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.3 Signed Authorization + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +== Agreement Phase == +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user. + + If the user agrees to the terms, the PISP uses + the Credential's privateKey to sign the challenge +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" + +note over D2 + DFSP has the signed challenge. + It now needs to ask the Auth-Service to verify + the signed challenge. +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg new file mode 100644 index 00000000..474f7023 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg @@ -0,0 +1,148 @@ + + + Transfer: 1.2.3 Signed Authorization + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user. + + + If the user agrees to the terms, the PISP uses + + + the Credential's privateKey to sign the challenge + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "GENERIC", + + + "genericSignedPayload": "utf-8 base64 encoded signature" + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + + DFSP has the signed challenge. + + + It now needs to ask the Auth-Service to verify + + + the signed challenge. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml new file mode 100644 index 00000000..8bde91c2 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.puml @@ -0,0 +1,82 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 1.2.4 Verify Authorization + + +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #Light +**""PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "authenticationResponse": "VERIFIED" +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +note over D2 + DFSPA now knows that the user signed this transaction + and can go ahead and initiate the transfer +end note + + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg new file mode 100644 index 00000000..1c7b39fe --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-2-4-verify-authorization.svg @@ -0,0 +1,196 @@ + + + Transfer: 1.2.4 Verify Authorization + + + + Mojaloop + + + + DFSP A + + + + + Switch + + + + Auth-Service + + + + DFSP A + + + (Payer) + + + + Generate a new + + + verificationRequestId + + + , and associate + + + it with the + + + thirdpartyTransactionRequestId + + + + POST /thirdpartyRequests/verifications + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "consentId": "123", + + + "signedPayloadType": "FIDO", + + + "fidoValue": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + Lookup this consent based on consentId + + + + Ensure the accountAddress matches what is in Consent + + + + Check that the signed bytes match the + + + publickey we have stored for the consent + + + + PUT /thirdpartyRequests/verifications/44444444-0000-0000-0000-000000000000 + + + FSPIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + "authenticationResponse": "VERIFIED" + + + } + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + DFSPA now knows that the user signed this transaction + + + and can go ahead and initiate the transfer + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml new file mode 100644 index 00000000..1af60155 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.puml @@ -0,0 +1,178 @@ +@startuml + +' define actor image +sprite $actor [25x48/16] { + 0000000000010000000000000 + 0000000006CAC910000000000 + 0000000095101292000000000 + 0000000651000119000000000 + 0000000B10000018400000000 + 0000001A10000016600000000 + 0000000B10000017510000000 + 000000083100001A210000000 + 0000000191000176110000000 + 000000003A866A61100000000 + 0000000000466211100000000 + 0003333333334443333310000 + 0088888888888888888892000 + 0821111111111111111118200 + 8311111111111111111111A00 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111111111111111111111A20 + A111551111111111138111A20 + A111661111111111139111A20 + A211661111111111139111A20 + A211661111111111139111A20 + A211661111161111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A2116611111A2111139111A20 + A7669611111A211113A666B20 + 36669611111A211113A666610 + 00016611111A2111139111110 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006611111A2111139100000 + 00006966666B7666679100000 + 0000266666666666664100000 + 0000000111111111111100000 + 0000000000000000000000000 +} + + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black +skinparam actor { + Bordercolor none + Backgroundcolor none + shadowing false +} + +hide footbox + +title Transfer: 1.3 Final transfer + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box +actor "<$actor>\nPayee" as CB + + + +== Transfer Phase == + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /transfers/55555555-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "fulfilment": "...", + "completedTimestamp": "2020-06-15T12:01:00.000", + "transferState": "COMMITTED" +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +S --> D3: ""200 OK"" +D3 -> CB: You have received funds! +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + + +D2 -> D2: Look up ""transactionRequestId"" from the ""transferId"" + +rnote over D2 #Light +**""PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", + "transactionState": "COMMITTED" +} +end note +D2 -> S: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PATCH /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +note over D1 + PISP can now inform the user the + funds have been sent +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg new file mode 100644 index 00000000..4adab1df --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/1-3-transfer.svg @@ -0,0 +1,309 @@ + + + Transfer: 1.3 Final transfer + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + + Payee + + + + + + + + Transfer Phase + + + DFSP A initiates a normal Mojaloop P2P Transfer + + + + Generate a new + + + transferId + + + , and associate + + + it with the + + + transactionRequestId + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "fulfilment": "...", + + + "completedTimestamp": "2020-06-15T12:01:00.000", + + + "transferState": "COMMITTED" + + + } + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + + + 200 OK + + + + You have received funds! + + + + PUT /transfers/55555555-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up + + + transactionRequestId + + + from the + + + transferId + + + + PATCH /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "ACCEPTED", + + + "transactionState": "COMMITTED" + + + } + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PATCH /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + + PISP can now inform the user the + + + funds have been sent + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml new file mode 100644 index 00000000..1252be90 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.puml @@ -0,0 +1,90 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.2.1 Bad Thirdparty Transaction Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +== Agreement Phase == +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP finds something wrong with this transaction request. + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6104", + "errorDescription": "Thirdparty request rejection", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg new file mode 100644 index 00000000..c62356df --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-2-1-bad-tx-request.svg @@ -0,0 +1,207 @@ + + + Transfer: 3.2.1 Bad Thirdparty Transaction Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + + Agreement Phase + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + DFSP finds something wrong with this transaction request. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6104", + + + "errorDescription": "Thirdparty request rejection", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml new file mode 100644 index 00000000..b6ebf6ce --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.puml @@ -0,0 +1,141 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.1 Bad Quote Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +D2 -> D2: Generate a unique transactionId for this transaction request:\n**""11111111-0000-0000-0000-000000000000""** + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestState": "RECEIVED" +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +rnote left of D2 #Light +**""POST /quotes""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "quoteId": "22222222-0000-0000-0000-000000000000", + "transactionId": "11111111-0000-0000-0000-000000000000", + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "personalInfo": { + "complexName": { + "firstName": "Ayesha", + "lastName": "Takia" + } + }, + "partyIdInfo": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + }, + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "note": "quote note" +} +end note +D2 -> S: ""POST /quotes"" +S --> D2: ""202 Accepted"" +S -> D3: ""POST /quotes"" +D3 --> S: ""202 Accepted"" + +D3 -> D3: Quote fails for some reason. + +rnote left of D3 #Light +**""PUT /quotes/22222222-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /quotes/22222222-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Quote failed, DFSP needs to inform PISP +end note + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream Failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg new file mode 100644 index 00000000..841d82c6 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-1-bad-quote-request.svg @@ -0,0 +1,369 @@ + + + Transfer: 3.3.1 Bad Quote Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + + Generate a unique transactionId for this transaction request: + + + 11111111-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestState": "RECEIVED" + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000 + + + + + 200 OK + + + + POST /quotes + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "quoteId": "22222222-0000-0000-0000-000000000000", + + + "transactionId": "11111111-0000-0000-0000-000000000000", + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "personalInfo": { + + + "complexName": { + + + "firstName": "Ayesha", + + + "lastName": "Takia" + + + } + + + }, + + + "partyIdInfo": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + }, + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "note": "quote note" + + + } + + + + POST /quotes + + + + + 202 Accepted + + + + POST /quotes + + + + + 202 Accepted + + + + Quote fails for some reason. + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "XXXX", + + + "errorDescription": "XXXX", + + + "extensionList": [] + + + } + + + } + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /quotes/22222222-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Quote failed, DFSP needs to inform PISP + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6003", + + + "errorDescription": "Downstream Failure", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml new file mode 100644 index 00000000..3a7f7879 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.puml @@ -0,0 +1,122 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.3.2 Bad Transfer Request + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box +box "DFSP B" + participant "DFSP B\n(Payee)" as D3 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +... DFSP A has received ""PUT /thirdpartyRequests/verifications from Auth-Service""... + +... DFSP A initiates a normal Mojaloop P2P Transfer ... + +D2 -> D2: Generate a new ""transferId"", and associate \n it with the ""transactionRequestId"" + +rnote over D2 #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +D2 -> S: ""POST /transfers"" +S --> D2: ""202 Accepted"" + +rnote over S #Light +**""POST /transfers""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: dfspb"" +{ + "transferId": "55555555-0000-0000-0000-000000000000", + "payerFsp": "dfspa", + "payeeFsp": "dfspb", + "amount": { + "amount": "100", + "currency": "USD" + }, + "expiration": "2020-06-15T13:00:00.000", + "ilpPacket": "...", + "condition": "...", +} +end note +S -> D3: ""POST /transfers"" +D3 --> S: ""202 Accepted"" + +rnote left of D3 #Light +**""PUT /transfers/55555555-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspb"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "XXXX", + "errorDescription": "XXXX", + "extensionList": [] + } +} +end note +D3 -> S: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +S --> D3: ""200 OK"" +S -> D2: ""PUT /transfers/55555555-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note left of D2 + Transfer failed, DFSP needs to inform PISP +end note + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6003", + "errorDescription": "Downstream failure", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg new file mode 100644 index 00000000..85626c5b --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-3-2-bad-transfer-request.svg @@ -0,0 +1,332 @@ + + + Transfer: 3.3.2 Bad Transfer Request + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + DFSP B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + DFSP B + + + (Payee) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + DFSP A has received + + + PUT /thirdpartyRequests/verifications from Auth-Service + + + DFSP A initiates a normal Mojaloop P2P Transfer + + + + Generate a new + + + transferId + + + , and associate + + + it with the + + + transactionRequestId + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + POST /transfers + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: dfspb + + + { + + + "transferId": "55555555-0000-0000-0000-000000000000", + + + "payerFsp": "dfspa", + + + "payeeFsp": "dfspb", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "expiration": "2020-06-15T13:00:00.000", + + + "ilpPacket": "...", + + + "condition": "...", + + + } + + + + POST /transfers + + + + + 202 Accepted + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspb + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "XXXX", + + + "errorDescription": "XXXX", + + + "extensionList": [] + + + } + + + } + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /transfers/55555555-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Transfer failed, DFSP needs to inform PISP + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6003", + + + "errorDescription": "Downstream failure", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml new file mode 100644 index 00000000..5bc586ee --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.puml @@ -0,0 +1,95 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Look up the ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Look up the ""consentId"" for this ""transactionRequestId"" +D2 -> D2: Look up the ""publicKey"" for this ConsentId. Check the signing of the signed challenge + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg new file mode 100644 index 00000000..213f6fc0 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg @@ -0,0 +1,261 @@ + + + Transfer: 3.4.1 Bad Signed Challenge - Self Hosted Auth-Service + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + and uses the FIDO API to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations/33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Look up the + + + transactionRequestId + + + for this + + + authorizationId + + + + Look up the + + + consentId + + + for this + + + transactionRequestId + + + + Look up the + + + publicKey + + + for this ConsentId. Check the signing of the signed challenge + + + + + Signed challenge is invalid. Transaction Request failed. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml new file mode 100644 index 00000000..ce3645d3 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.puml @@ -0,0 +1,149 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S + participant "Auth-Service" as AUTHS +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +... PISP has initiated Thirdparty Transaction Request with ""POST /thirdpartyRequests/transactions""... + +... DFSP A has received quote, and asked PISP to verify... + +note right of D1 + PISP looks up the ""transactionRequestId"" and + checks the quote with the user, + and uses the FIDO API to sign the + the **""challenge""** string +end note + +rnote right of D1 #Light +**""PUT /thirdpartyRequests/authorizations""** +**"" /33333333-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "responseType": "ACCEPTED" + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } + } +} +end note +D1 -> S: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +S --> D1: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/authorizations""\n""/33333333-0000-0000-0000-000000000000"" +D2 --> S: ""200 OK"" + +D2 -> D2: Lookup ""transactionRequestId"" for this ""authorizationId"" +D2 -> D2: Lookup ""consentId"" for this ""transactionRequestId"" + + +D2 -> D2: Generate a new ""verificationRequestId"", and associate \n it with the ""thirdpartyTransactionRequestId"" + +rnote left of D2 #Light +**""POST /thirdpartyRequests/verifications""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: central-auth"" +{ + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + "challenge": """", + "consentId": "123", + "signedPayloadType": "FIDO", + "fidoValue": { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" + } +} +end note +D2 -> S: ""POST /thirdpartyRequests/verifications"" +S --> D2: ""202 Accepted"" +S -> AUTHS: ""POST /thirdpartyRequests/verifications"" +AUTHS --> S: ""202 Accepted"" + +AUTHS -> AUTHS: Lookup this consent based on consentId +AUTHS -> AUTHS: Ensure the accountAddress matches what is in Consent +AUTHS -> AUTHS: Check that the signed bytes match the \npublickey we have stored for the consent + +rnote right of AUTHS #Light +**""PUT /thirdpartyRequests/verifications""** +**"" /44444444-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: central-auth"" +""FSPIOP-Destination: dfspa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +AUTHS -> S: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +S --> AUTHS: ""200 OK"" +S -> D2: ""PUT /thirdpartyRequests/verifications""\n"" /44444444-0000-0000-0000-000000000000/error"" +D2 --> S: ""200 OK"" + +note over D2 + Signed challenge is invalid. Transaction Request failed. +end note + + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions""** +**"" /00000000-0000-0000-0000-000000000000/error""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "errorInformation": { + "errorCode": "6201", + "errorDescription": "Invalid transaction signature", + "extensionList": [] + } +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +S --> D2: ""200 OK"" +S -> D1: ""PUT /thirdpartyRequests/transactions""\n"" /00000000-0000-0000-0000-000000000000/error"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg new file mode 100644 index 00000000..58c8e995 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg @@ -0,0 +1,439 @@ + + + Transfer: 3.4.2 Bad Signed Challenge - Hub Hosted Auth-Service + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + + + + + + + + + + + PISP Server + + + + Switch + + + + Auth-Service + + + + DFSP A + + + (Payer) + + + PISP has initiated Thirdparty Transaction Request with + + + POST /thirdpartyRequests/transactions + + + DFSP A has received quote, and asked PISP to verify + + + + + PISP looks up the + + + transactionRequestId + + + and + + + checks the quote with the user, + + + and uses the FIDO API to sign the + + + the + + + challenge + + + string + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "responseType": "ACCEPTED" + + + "signedPayload": { + + + "signedPayloadType": "FIDO", + + + "fidoSignedPayload": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + } + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + PUT /thirdpartyRequests/authorizations + + + /33333333-0000-0000-0000-000000000000 + + + + + 200 OK + + + + Lookup + + + transactionRequestId + + + for this + + + authorizationId + + + + Lookup + + + consentId + + + for this + + + transactionRequestId + + + + Generate a new + + + verificationRequestId + + + , and associate + + + it with the + + + thirdpartyTransactionRequestId + + + + POST /thirdpartyRequests/verifications + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: central-auth + + + { + + + "verificationRequestId": "44444444-0000-0000-0000-000000000000", + + + "challenge": + + + <base64 encoded binary - the encoded challenge> + + + , + + + "consentId": "123", + + + "signedPayloadType": "FIDO", + + + "fidoValue": { + + + "id": "string", + + + "rawId": "string - base64 encoded utf-8", + + + "response": { + + + "authenticatorData": "string - base64 encoded utf-8", + + + "clientDataJSON": "string - base64 encoded utf-8", + + + "signature": "string - base64 encoded utf-8", + + + "userHandle": "string - base64 encoded utf-8", + + + }, + + + "type": "public-key" + + + } + + + } + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + POST /thirdpartyRequests/verifications + + + + + 202 Accepted + + + + Lookup this consent based on consentId + + + + Ensure the accountAddress matches what is in Consent + + + + Check that the signed bytes match the + + + publickey we have stored for the consent + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + FSPIOP-Source: central-auth + + + FSPIOP-Destination: dfspa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/verifications + + + /44444444-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + + Signed challenge is invalid. Transaction Request failed. + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "errorInformation": { + + + "errorCode": "6201", + + + "errorDescription": "Invalid transaction signature", + + + "extensionList": [] + + + } + + + } + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + + + PUT /thirdpartyRequests/transactions + + + /00000000-0000-0000-0000-000000000000/error + + + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml new file mode 100644 index 00000000..dfcae669 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.puml @@ -0,0 +1,77 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title Transfer: 3.Thirdparty Transaction Request Times Out + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + + +rnote right of D1 #Light +**""POST /thirdpartyRequests/transactions""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +{ + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + "payee": { + "partyIdInfo": { + "partyIdType": "MSISDN", + "partyIdentifier": "+4412345678", + "fspId": "dfspb" + } + }, + "payer": { + "partyIdType": "THIRD_PARTY_LINK", + "partyIdentifier": "qwerty-56789", + "fspId": "dfspa" + }, + "amountType": "SEND", + "amount": { + "amount": "100", + "currency": "USD" + }, + "transactionType": { + "scenario": "TRANSFER", + "initiator": "PAYER", + "initiatorType": "CONSUMER" + }, + "expiration": "2020-06-15T22:17:28.985-01:00" +} +end note +D1 -> S: ""POST /thirdpartyRequests/transactions"" +S --> D1: ""202 Accepted"" +S -> D2: ""POST /thirdpartyRequests/transactions"" +D2 --> S: ""202 Accepted"" + + +... DFSP doesn't respond for some reason... + + +D1 -> D1: Thirdparty Transaction Request expiration reached + +note over D1 + PISP informs their user that the transaction failed. + +end note + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg new file mode 100644 index 00000000..e9ba7851 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/3-6-tpr-timeout.svg @@ -0,0 +1,157 @@ + + + Transfer: 3.Thirdparty Transaction Request Times Out + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + + + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + POST /thirdpartyRequests/transactions + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + { + + + "transactionRequestId": "00000000-0000-0000-0000-000000000000", + + + "payee": { + + + "partyIdInfo": { + + + "partyIdType": "MSISDN", + + + "partyIdentifier": "+4412345678", + + + "fspId": "dfspb" + + + } + + + }, + + + "payer": { + + + "partyIdType": "THIRD_PARTY_LINK", + + + "partyIdentifier": "qwerty-56789", + + + "fspId": "dfspa" + + + }, + + + "amountType": "SEND", + + + "amount": { + + + "amount": "100", + + + "currency": "USD" + + + }, + + + "transactionType": { + + + "scenario": "TRANSFER", + + + "initiator": "PAYER", + + + "initiatorType": "CONSUMER" + + + }, + + + "expiration": "2020-06-15T22:17:28.985-01:00" + + + } + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + + POST /thirdpartyRequests/transactions + + + + + 202 Accepted + + + DFSP doesn't respond for some reason + + + + Thirdparty Transaction Request expiration reached + + + + + PISP informs their user that the transaction failed. + + diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml new file mode 100644 index 00000000..c8ca6b83 --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.puml @@ -0,0 +1,67 @@ +@startuml + +' declaring skinparam +skinparam sequenceMessageAlign center +skinparam shadowing false +skinparam defaultFontName Verdana +skinparam monochrome true +skinparam SequenceLifeLineBackgroundColor WhiteSmoke +skinparam SequenceLifeLineBorderColor Black +skinparam ParticipantFontStyle Bold +skinparam ParticipantFontSize 20 +skinparam ParticipantBackgroundColor WhiteSmoke +skinparam ArrowColor Black + +hide footbox + +title PISPGetTransactionRequest + +box "PISP" +participant "PISP Server" as D1 +end box +box "Mojaloop" + participant Switch as S +end box +box "DFSP A" + participant "DFSP A\n(Payer)" as D2 +end box + +autonumber 1 "GTR-#" + +note over S + Assuming a previously created thirdparty transaction request with id: ""00000000-0000-0000-0000-000000000000"" + +end note + + + +rnote right of D1 #Light +**""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: pispa"" +""FSPIOP-Destination: dfspa"" +end note + +D1 -> S: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D1: ""202 Accepted"" + +S -> D2: ""GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D2 --> S: ""202 Accepted"" + +D2 -> D2: DFSP looks up already created \nthirdparty transaction request +D2 -> D2: DFSP ensures that the FSPIOP-Source (pisp)\nis the same as the original sender of \n""POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" + +rnote left of D2 #Light +**""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000""** +""FSPIOP-Source: dfspa"" +""FSPIOP-Destination: pispa"" +{ + "transactionRequestState": "ACCEPTED", +} +end note +D2 -> S: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +S --> D2: ""200 OK"" + +S -> D1: ""PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000"" +D1 --> S: ""200 OK"" + +@enduml diff --git a/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg new file mode 100644 index 00000000..ffaa28ad --- /dev/null +++ b/vuepress/docs/api/thirdparty/assets/diagrams/transfer/get_transaction_request.svg @@ -0,0 +1,153 @@ + + + PISPGetTransactionRequest + + + + PISP + + + + Mojaloop + + + + DFSP A + + + + + PISP Server + + + + Switch + + + + DFSP A + + + (Payer) + + + + + Assuming a previously created thirdparty transaction request with id: + + + 00000000-0000-0000-0000-000000000000 + + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: pispa + + + FSPIOP-Destination: dfspa + + + + GTR-1 + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-2 + + + 202 Accepted + + + + GTR-3 + + + GET /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-4 + + + 202 Accepted + + + + GTR-5 + + + DFSP looks up already created + + + thirdparty transaction request + + + + GTR-6 + + + DFSP ensures that the FSPIOP-Source (pisp) + + + is the same as the original sender of + + + POST /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + FSPIOP-Source: dfspa + + + FSPIOP-Destination: pispa + + + { + + + "transactionRequestState": "ACCEPTED", + + + } + + + + GTR-7 + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-8 + + + 200 OK + + + + GTR-9 + + + PUT /thirdpartyRequests/transactions/00000000-0000-0000-0000-000000000000 + + + + + GTR-10 + + + 200 OK + + diff --git a/vuepress/docs/api/thirdparty/data-models.md b/vuepress/docs/api/thirdparty/data-models.md new file mode 100644 index 00000000..0fa1c4b4 --- /dev/null +++ b/vuepress/docs/api/thirdparty/data-models.md @@ -0,0 +1,991 @@ +# Data Models + +Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Third Party API Elements](#ThirdPartyAPIElements) + 3.1 [Resources](#Resources) + 3.2 [Data Models](#DataModels) + 3.3 [Error Codes](#ErrorCodes) +# 1. Preface +This section contains information about how to use this document. + +## 1.1 Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2 Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3 References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document specifies the data model used by the Mojaloop Third Party API ("the API"). + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Third Party API Elements + +This section describes the content of the API which will be used by PISPs and DFSPs. + +The content of the API falls into two sections: + +1. [Transaction Patterns - Linking](./transaction-patterns-linking.md) describes the process for linking customer accounts and providing a general permission mechanism for PISPs to perform operations on those accounts +2. [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) describes the transfer of funds at the instigation of a PISP. + +The API is used by the following different types of participant, as follows: + 1. PISPs + 2. DFSPs who offer services to their customer which allow the customer to access their account via one or more PISPs + 3. Auth-Services + 4. The Mojaloop switch + +Each resource in the API definition is accompanied by a definition of the type(s) of participant allowed to access it. + +## 3.1 Resources + +The API contains the following resources: + +### 3.1.1 **/accounts** + +The **/accounts** resource is used to request information from a DFSP relating to the accounts +it holds for a given identifier. The identifier is a user-provided value which the user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +The DFSP returns a set of information about the accounts it is prepared to divulge to the PISP. +The PISP can then display the names of the accounts to the user, and allow the user to select +the accounts with which they wish to link via the PISP. + +The **/accounts** resource supports the endpoints described below. + +#### 3.1.1.1 Requests + +This section describes the services that a PISP can request on the /accounts resource. + +##### 3.1.1.1.1 **GET /accounts/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /accounts/**_{ID}_ is used to lookup information about the requested +user's accounts, defined by an identifier *{ID}*, where *{ID}* is an identifier a user +uses to access their account with the DFSP, such as a phone number, email address, or +some other identifier previously provided by the DFSP. + +Callback and data model information for **GET /accounts/**_{ID}_: +- Callback - **PUT /accounts/**_{ID}_ +- Error Callback - **PUT /accounts/**_{ID}_**/error** +- Data Model – Empty body + +#### 3.1.1.2 Callbacks + +The responses for the **/accounts** resource are as follows + +##### 3.1.1.2.1 **PUT /accounts/**_{ID}_ + +Used by: DFSP + +The **PUT /accounts/**_{ID}_ response is used to inform the requester of the result of a request +for accounts information. The identifier ID given in the call are the +values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| accountList | 1 | AccountList | Information about the accounts that the DFSP associates with the identifier sent by the PISP. | + +##### 3.1.1.2.2 **PUT /accounts/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /accounts/**_{ID}_**/error** response is used to inform the requester that an account list +request has given rise to an error. The identifier ID given in the call are +the values given in the original request (see Section 3.1.1.1.1 above.) + +The data content of the message is given below. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.2 **/consentRequests** + +The **/consentRequests** resource is used by a PISP to initiate the process of linking with a DFSP’s +account on behalf of a user. The PISP contacts the DFSP and sends a list of the permissions that +it wants to obtain and the accounts for which it wants permission. + +#### 3.1.2.1 Requests + +This section describes the services that can be requested by a client on the API resource +**/consentRequests**. +##### 3.1.2.1.1 **GET /consentRequests/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /consentRequests/**_{ID}_ is used to get information about a previously +requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the +request by the PISP when the PISP originated the request. + +Callback and data model information for **GET /consentRequests/**_{ID}_: +- Callback – **PUT /consentRequests/**_{ID}_ +- Error Callback – **PUT /consentRequests/**_{ID}_**/error** +- Data Model – Empty body + +##### 3.1.2.1.2 **POST /consentRequests** + +Used by: PISP + +The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more +accounts owned by a customer of the DFSP for the PISP who sends the request. + +Callback and data model for **POST /consentRequests**: +- Callback: **PUT /consentRequests/**_{ID}_ +- Error callback: **PUT /consentRequests/**_{ID}_**/error** +- Data model – see below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent request object. The ID should be reused for resends of the same consent request. A new ID should be generated for each new consent request. | +| userId | 1 | String(1..128) | The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest` | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1..256 | ConsentRequestChannelType | A collection of the types of authentication that the DFSP may use to verify that its customer has in fact requested access for the PISP to the accounts requested. | +| callbackUri | 1 | Uri | The callback URI that the user will be redirected to after completing verification via the WEB authorization channel. This field is mandatory as the PISP does not know ahead of time which AuthChannel the DSFP will use to authenticate their user. | + +#### 3.1.2.2 Callbacks + +This section describes the callbacks that are used by the server under the resource /consentRequests. + +##### 3.1.2.2.1 **PUT /consentRequests/**_{ID}_ + +Used by: DFSP + +A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, +and (2) communicate to the PISP which `authChannel` it should use to authenticate their user +with. + +When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all +the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization +process may result in additional privileges being granted by the account holder to the PISP. The +**PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a +particular authorization request. The data model for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | One or more requests for access to a particular account. In each case, the address of the account and the types of access required are given. | +| authChannels | 1 | ConsentRequestChannelType | A list of one element, which the DFSP uses to inform the PISP of the selected authorization channel. | +| callbackUri | 0..1 | Uri |The callback URI that the user will be redirected to after completing verification via the WEB authorization channel | +| authUri | 0..1 | Uri | The URI that the PISP should call to complete the linking procedure if completion is required. | + + +##### 3.1.2.2.2 **PATCH /consentRequests/**_{ID}_ + +Used by: PISP + +After the user completes an out-of-band authorization with the DFSP, the PISP will receive +a token which they can use to prove to the DFSP that the user trusts this PISP. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authToken | 1 | BinaryString |The token given to the PISP by the DFSP as part of the out-of-band authentication process | + +#### 3.1.2.3 Error callbacks + +This section describes the error callbacks that are used by the server under the resource +**/consentRequests**. + +##### 3.1.2.3.1 **PUT /consentRequests/**_{ID}_**/error** + +Used by: DFSP + +If the server is unable to complete the consent request, or if an out-of-band processing error or +another processing error occurs, the error callback **PUT /consentRequests/**_{ID}_**/error** is used. The +*{ID}* in the URI should contain the *{ID}* that was used in the **GET /consentRequests/**_{ID}_ +request or the **POST /consentRequests** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + + +### 3.1.3 **/consents** + +The **/consents** resource is used to negotiate a series of permissions between the PISP and the +DFSP which owns the account(s) on behalf of which the PISP wants to transact. + +A **/consents** call is originally sent to the PISP by the DFSP following the original consent +request process described in Section 3.1.2.1.2 above. At the close of this process, the DFSP +which owns the customer’s account(s) will have satisfied itself that its customer really has +requested that the PISP be allowed access to their accounts, and will have defined the accounts in +question and the type of access which is to be granted. +#### 3.1.3.1 Requests +The **/consents** resource will support the following requests. +##### 3.1.3.1.1 **GET /consents/**_{ID}_ + +Used by: DFSP + +The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The +*{ID}* used in the URI of the request should be the consent request ID which was used to identify +the consent when it was created. + +Callback and data model information for **GET /consents/**_{ID}_: +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.3.1.2 **POST /consents** + +Used by: DFSP + +The **POST /consents** request is used to request the creation of a consent for interactions between +a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + +Callback and data model information for **POST /consents/**: + +- Callback – **PUT /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** +- Data Model – defined below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| consentId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the consent object. The ID should be reused for resends of the same consent. A new ID should be generated for each new consent.| +| consentRequestId | 1 | CorrelationId | The ID given to the original consent request on which this consent is based. | +| scopes | 1..256 | Scope | A list Scope objects, which represent the accounts and attached permissions on which the DFSP is prepared to grant specified permissions to the PISP. | +| status | 1 | ConsentStatus | The status of the Consent. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | +##### 3.1.3.1.3 **DELETE /consents/**_{ID}_ + +Used by PISP, DFSP + +The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. +For tracing and auditing purposes, the switch should be sure not to delete the consent physically; +instead, information relating to the consent should be marked as deleted and requests relating to the +consent should not be honoured. + +> Note: the ALS should verify that the participant who is requesting the deletion is either the +> initiator named in the consent or the account holding institution named in the consent. If any +> other party attempts to delete a consent, the request should be rejected, and an error raised. + +Callback and data model information for **DELETE /consents/**_{ID}_: +- Callback – **PATCH /consents/**_{ID}_ +- Error Callback – **PUT /consents/**_{ID}_**/error** + +#### 3.1.3.2 Callbacks +The **/consents** resource supports the following callbacks: +##### 3.1.3.2.1 **PATCH/consents/**_{ID}_ + +Used by: Auth-Service, DFSP + +**PATCH /consents/**_{ID}_ is used in 2 places: +1. To inform the PISP that the `consent.credential` is valid and the account linking process completed + successfully. +2. To inform the PISP or the DFSP that the Consent has been revoked. + +In the first case, a DFSP sends a **PATCH/consents/**_{ID}_ request to the PISP with a `credential.status` +of `VERIFIED`. + +In the second case, an Auth-Service or DFSP sends a **PATCH/consents/**_{ID}_ request with a `status` of +`REVOKED`, and the `revokedAt` field set. + +The syntax of this call complies with the JSON Merge Patch specification [RFC-7386](https://datatracker.ietf.org/doc/html/rfc7386) +rather than the JSON Patch specification [RFC-6902](https://datatracker.ietf.org/doc/html/rfc6902). +The **PATCH /consents/**_{ID}_ resource contains a set of proposed changes to the current state of the +permissions relating to a particular authorization grant. The data model +for this call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| revokedAt | 0..1 | DateTime | The DateTime the consent was revoked at. | +| credential | 0..1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.3.2.2 **PUT /consents/**_{ID}_ + +Used by: PISP + +The **PUT /consents/**_{ID}_ resource is used to return information relating to the consent object +whose `consentId` is given in the URI. And for registering a credential for the consent. The +data returned by the call is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopes | 1..256 | Scope | The scopes covered by the consent. | +| status | 0..1 | ConsentStatus | The status of the Consent. | +| credential | 1 | Credential | The credential which is being used to support the consents. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | +#### 3.1.3.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource **/consents**. +##### 3.1.3.3.1 **PUT /consents/**_{ID}_**/error** + +Used by: PISP, DFSP, Auth-Service + +If the server is unable to complete the consent, or if an out-of-loop processing error or another +processing error occurs, the error callback **PUT /consents/**_{ID}_**/error** is used. The *{ID}* in the +URI should contain the *{ID}* that was used in the **GET /consents/**_{ID}_ request or the +**POST /consents** request. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.4 **/parties** + +The **/parties** resource will be used by the PISP to identify a party to a transfer. This will be +used by the PISP to identify the payee DFSP when it requests a transfer. + +The PISP will be permitted to issue a **PUT /parties** response. Although it does not own any +transaction accounts, there are circumstances in which another party may want to pay a customer +via their PISP identification: for instance, where the customer is at a merchant’s premises and +tells the merchant that they would like to pay via their PISP app. In these circumstances, the PISP +will need to be able to confirm that it does act for the customer. +#### 3.1.4.1 Requests + +The **/parties** resource will support the following requests. +##### 3.1.4.1.1 **GET /parties** + +Used by: PISP + +The **GET /parties** resource will use the same form as the resource described in +[Section 6.3.3.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6331-get-partiestypeid) of Ref. 1 above. +#### 3.1.4.2 Callbacks +The parties resource will support the following callbacks. +##### 3.1.4.2.1 **PUT /parties** + +Used by: DFSP + +The **PUT /parties** resource will use the same form as the resource described in +[Section 6.3.4.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6341-put-partiestypeid) of Ref. 1 above. + +### 3.1.5 **/services** +The **/services** resource is a new resource which enables a participant to query for other +participants who offer a particular service. The requester will issue a `GET` request, specifying +the type of service for which information is required as part of the query string. The switch will +respond with a list of the current DFSPs in the scheme which are registered as providing that +service. +#### 3.1.5.1 Requests +The services resource will support the following requests. +#### 3.1.5.2 **GET /services/**_{ServiceType}_ + +Used by: DFSP, PISP + +The HTTP request **GET /services/**_{ServiceType}_ is used to find out the names of the participants in a +scheme which provide the type of service defined in the *{ServiceType}* parameter. The *{ServiceType}* parameter +should specify a value from the ServiceType enumeration. If it does not, the request will be +rejected with an error. + +Callback and data model information for **GET /services/**_{ServiceType}_: +- Callback - **PUT /services/**_{ServiceType}_ +- Error Callback - **PUT /services/**_{ServiceType}_**/error** +- Data Model – Empty body +#### 3.1.5.3 Callbacks +This section describes the callbacks that are used by the server for services provided by the +resource **/services**. +##### 3.1.5.3.1 **PUT /services/**_{ServiceType}_ + +Used by: Switch + +The callback **PUT /services/**_{ServiceType}_ is used to inform the client of a successful result of +the service information lookup. The information is returned in the following form: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| providers | 0...256 | FspId | A list of the Ids of the participants who provide the service requested. | + +##### 3.1.5.3.2 **PUT /services/**_{ServiceType}_**/error** + +Used by: Switch + +If the server encounters an error in fulfilling a request for a list of participants who +provide a service, the error callback **PUT /services/**_{ServiceType}_**/error** is used to inform the +client that an error has occurred. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +### 3.1.6 **thirdpartyRequests/authorizations** + +The **/thirdpartyRequests/authorizations** resource is analogous to the **/authorizations** resource + described in [Section 6.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#66-api-resource-authorizations) of Ref. 1 above. The DFSP uses it to request the PISP to: + +1. Display the information defining the terms of a proposed transfer to its customer; +2. Obtain the customer’s confirmation that they want the transfer to proceed; +3. Return a signed version of the terms which the DFSP can use to verify the consent + +The **/thirdpartyRequests/authorizations** resource supports the endpoints described below. +#### 3.1.6.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/authorizations** resource. +##### 3.1.6.1.1 **GET /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: DFSP + +The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating +to a previously issued authorization request. The *{ID}* in the request should match the +`authorizationRequestId` which was given when the authorization request was created. + +Callback and data model information for **GET /thirdpartyRequests/authorizations/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.6.1.2 **POST /thirdpartyRequests/authorizations** + +Used by: DFSP + +The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a + customer for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/authorizations:** + +- Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** +- Data Model – See Table below + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authorizationRequestId | 1 | CorrelationId | Common ID between the PISP and the Payer DFSP for the authorization request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| transactionRequestId | 1 | CorrelationId | The unique identifier of the transaction request for which authorization is being requested. | +| challenge | 1 | BinaryString | The challenge that the PISP’s client is to sign. | +| transferAmount | 1 | Money | The amount that will be debited from the sending customer’s account as a consequence of the transaction. | +| payeeReceiveAmount | 1 | Money | The amount that will be credited to the receiving customer’s account as a consequence of the transaction. | +| fees | 1 | Money | The amount of fees that the paying customer will be charged as part of the transaction. | +| payer | 1 | PartyIdInfo | Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| payee | 1 | Party | Information about the Payee in the proposed transaction | +| transactionType | 1 | TransactionType | The type of the transaction. | +| expiration | 1 | DateTime | The time by which the transfer must be completed, set by the payee DFSP. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | + +#### 3.1.6.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/authorizations** resource +##### 3.1.6.2.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_ + +Used by: PISP + +After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the +transaction to their user, and request that the client sign the `challenge` field using the credential +they previously registered. + +The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| responseType | 1 | AuthorizationResponseType | `ACCEPTED` or `REJECTED` | +| signedPayload | 0..1 | SignedPayload | If the `responseType` is `ACCEPTED`, `signedPayload` is required. | + +#### 3.1.6.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/authorizations**. +##### 3.1.6.3.1 **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/authorizations/**_{ID}_**/error** resource will have the same content +as the **PUT /authorizations/**_{ID}_**/error** resource described in [Section 6.6.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6651-put-authorizationsiderror) +of Ref. 1 above. +### 3.1.7 **/thirdpartyRequests/transactions** +The **/thirdpartyRequests/transactions` resource is analogous to the `/transactionRequests** +resource described in [Section 6.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#64-api-resource-transactionrequests) of Ref. 1 above. The PISP uses it to request the +owner of the PISP’s customer’s account to transfer a specified amount from the customer’s +account with the DFSP to a named Payee. + +The **/thirdpartyRequests/transactions** resource supports the endpoints described below. +#### 3.1.7.1 Requests + +This section describes the services that a client can request on the +**/thirdpartyRequests/transactions** resource. +##### 3.1.7.1.1 **GET /thirdpartyRequests/transactions/**_{ID}_ + +Used by: PISP + +The HTTP request **GET /thirdpartyRequests/transactions/**_{ID}_ is used to get information +relating to a previously issued transaction request. The *{ID}* in the request should +match the `transactionRequestId` which was given when the transaction request was created. + +Callback and data model information for **GET /thirdpartyRequests/transactions/**_{ID}_: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.7.1.2 **POST /thirdpartyRequests/transactions** + +Used by: PISP + +The HTTP request **POST /thirdpartyRequests/transactions** is used to request the creation +of a transaction request on the server for the transfer described in the request. + +Callback and data model information for **POST /thirdpartyRequests/transactions**: +- Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestId | 1 | CorrelationId |Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. | +| payee | 1 | Party |Information about the Payee in the proposed financial transaction. | +| payer | 1 | PartyIdInfo |Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction. | +| amountType | 1 | AmountType | SEND for send amount, RECEIVE for receive amount. | +| amount | 1 | Money | Requested amount to be transferred from the Payer to Payee. | +| transactionType | 1 | TransactionType |Type of transaction | +| note | 0..1 | Note | Memo assigned to Transaction. | +| expiration | 0..1 | DateTime |Can be set to get a quick failure in case the peer FSP takes too long to respond. Also, it may be beneficial for Consumer, Agent, Merchant to know that their request has a time limit. | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment. | +#### 3.1.7.2 Callbacks +The following callbacks are supported for the **/thirdpartyRequests/transactions** resource +##### 3.1.7.2.1 **PUT /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +After a PISP requests the creation of a Third Party Transaction request (**POST /thirdpartyRequests/transactions**) +or the status of a previously created Third Party Transaction request +(**GET /thirdpartyRequests/transactions/**_{ID}_), the DFSP will send this callback. + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request. | +| extensionList | 0..1 | ExtensionList | Optional extension, specific to deployment | + +##### 3.1.7.2.2 **PATCH /thirdpartyRequests/transactions/**_{ID}_ + +Used by: DFSP + +The issuing PISP will expect a response to their request for a transfer which describes +the finalised state of the requested transfer. This response will be given by a `PATCH` call on the +**/thirdpartyRequests/transactions/**_{ID}_ resource. The *{ID}* given in the query string should be +the `transactionRequestId` which was originally used by the PISP to identify the transaction +request (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above.) + +The data model for this endpoint is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| completedTimestamp | 0..1 | DateTime |Time and date when the transaction was completed, if it was completed. | +| transactionRequestState | 1 | TransactionRequestState | State of the transaction request | +| transactionState | 1 | TransactionState | State of the transaction created by the DFSP in response to this transaction request | +| extensionList | 0..1 | ExtensionList |Optional extension, specific to deployment | + +#### 3.1.7.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/transactions**. +##### 3.1.7.3.1 **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** + +Used by: DFSP + +The **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** resource will have the same content as +the **PUT /transactionRequests/**_{ID}_**/error** resource described in [Section 6.4.5.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#6451-put-transactionrequestsiderror) of Ref. 1 above. + +### 3.1.8 **/thirdpartyRequests/verifications** + +The **/thirdpartyRequests/verifications** resource is used by a Payer DFSP to verify that an authorization +response received from a PISP was signed using the correct private key, in cases where the authentication service +to be used is implemented by the switch and not internally by the DFSP. The DFSP sends the original +challenge and the signed response to the authentication service, together with the `consentId` to be used +for the verification. The authentication service compares the response with the result of signing the +challenge with the private key associated with the `consentId`, and, if the two match, it returns a +positive result. Otherwise, it returns an error. + +The **/thirdpartyRequests/verifications** resource supports the endpoints described below. +#### 3.1.8.1 Requests +This section describes the services that a client can request on the **/thirdpartyRequests/verifications** +resource. +##### 3.1.8.1.1 **GET /thirdpartyRequests/verifications/**_{ID}_ + +Used by: DFSP + +The HTTP request **/thirdpartyRequests/verifications/**_{ID}_ is used to get information regarding a previously +created or requested authorization. The *{ID}* in the URI should contain the verification request ID +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) below) that was used for the creation of the transfer.Callback and data model +information for **GET /thirdpartyRequests/verifications/**_{ID}_: + +- Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback – **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** +- Data Model – Empty body +##### 3.1.8.1.2 **POST /thirdpartyRequests/verifications** + +Used by: DFSP + +The **POST /thirdpartyRequests/verifications** resource is used to request confirmation from an authentication +service that a challenge has been signed using the correct private key. + +Callback and data model information for **POST /thirdpartyRequests/verifications**: +- Callback - **PUT /thirdpartyRequests/verifications/**_{ID}_ +- Error Callback - **PUT /thirdpartyRequests/verifications /**_{ID}_**/error** +- Data Model – See Table below + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| verificationRequestId | 1 | CorrelationId |Common ID between the DFSP and authentication service for the verification request object. The ID should be reused for resends of the same authorization request. A new ID should be generated for each new authorization request. | +| challenge | 1 | BinaryString |The challenge originally sent to the PISP | +| consentId | 1 | CorrelationId |Common Id between the DFSP and the authentication service for the agreement against which the authentication service is to evaluate the signature | +| signedPayloadType | 1 | SignedPayloadType | The type of the SignedPayload, depending on the type of credential registered by the PISP | +| genericSignedPayload | 0..1 | BinaryString | Required if signedPayloadType is GENERIC. The signed challenge returned by the PISP. A BinaryString representing a signature of the challenge + private key of the credential. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is FIDO. The signed challenge returned by the PISP in the form of a [`FIDOPublicKeyCredentialAssertion` Object](https://w3c.github.io/webauthn/#iface-pkcredential) | + +#### 3.1.8.2 Callbacks +This section describes the callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications** +##### 3.1.8.2.1 **PUT /thirdpartyRequests/verifications/**_{ID}_ + +Used by: Auth Service + +The callback **PUT /thirdpartyRequests/verifications/**_{ID}_ is used to inform the client of the result +of an authorization check. The *{ID}* in the URI should contain the `authorizationRequestId` +(see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the check, or the *{ID}* that was +used in the **GET /thirdpartyRequests/verifications/**_{ID}_. The data model for this resource is as follows: + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticationResponse | 1 | AuthenticationResponse | The result of the authorization check. | +#### 3.1.8.3 Error callbacks +This section describes the error callbacks that are used by the server under the resource +**/thirdpartyRequests/verifications**. +##### 3.1.8.3.1 **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** + +Used by: Auth Service + +If the server is unable to complete the authorization request, or another processing error occurs, the +error callback **PUT /thirdpartyRequests/verifications/**_{ID}_**/error** is used.The *{ID}* in the URI should +contain the `verificationRequestId` (see [Section 3.1.8.1.2](#31812-post-thirdpartyrequestsverifications) above) which was used to request the +check, or the *{ID}* that was used in the **GET /thirdpartyRequests/verifications/**_{ID}_. + +The data model for this resource is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| errorInformation | 1 | ErrorInformation | Information describing the error and error code. | + +## 3.2 Data Models + +The following additional data models will be required to support the Third Party API + +### 3.2.1 Element definitions +#### 3.2.1.1 Account + +The Account data model contains information relating to an account. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 | AccountAddress | An address which can be used to identify the account | +| currency | 1 | Currency | The currency in which the account is denominated | +| accountNickname | 0..1 | Name | Display name of the account, as set by the account owning DFSP. This will normally be a type name, such as “Transaction Account” or “Savings Account” | +#### 3.2.1.2 AccountAddress + +The AccountAddress data type is a variable length string with a maximum size of 1023 characters and consists of: +- Alphanumeric characters, upper or lower case. (Addresses are case-sensitive so that they can contain data encoded in formats such as base64url.) +- Underscore (\_) +- Tilde (~) +- Hyphen (-) +- Period (.) Addresses MUST NOT end in a period (.) character + +An entity providing accounts to parties (i.e. a participant) can provide any value for an `AccountAddress` that is meaningful to that entity. +It does not need to provide an address that makes the account identifiable outside the entity’s domain. + +> ***IMPORTANT:* The policy for defining addresses and the life-cycle of these is at the discretion of the address space owner (the payer DFSP in this case).** +#### 3.2.1.3 AccountList +The AccountList data model is used to hold information about the accounts that a party controls. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| account | 1..256 | Account | Information relating to an account that a party controls. | + + +#### 3.2.1.5 AuthenticationResponse + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| AuthenticationResponse | 1 | Enum of String(1..32) | See [Section 3.2.2.1](#3221-AuthenticationResponse) below (AuthenticationResponse) for more information on allowed values.| +#### 3.2.1.6 BinaryString +The BinaryString type used in these definitions is as defined in [Section 7.2.17](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7217-binarystring) of Ref. 1 above. +#### 3.2.1.7 ConsentRequestChannelType +The ConsentRequestChannelType is used to hold an instance of the ConsentRequestChannelType enumeration. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentRequestChannelType | 1 | Enum of String(1..32) | See [Section 3.2.2.4](#3223-consentrequestchanneltype) below ( ConsentRequestChannelType) for more information on allowed values. | + +#### 3.2.1.8 ConsentStatus +The ConsentStatus type stores the status of a consent request, as described in [Section 3.1.3.2.2](#31322-put-consentsid) above. Its data model is as follows: +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| ConsentStatus | 1 | Enum of String(1..32) | See [Section 3.2.2.5](#3224-consentstatustype) below (ConsentStatusType) for more information on allowed values.| + +#### 3.2.1.9 CorrelationId +The CorrelationId type used in these definitions is as defined in [Section 7.3.8](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#738-correlationid) of Ref. 1 above. +##### 3.2.1.10 Credential +The Credential object is used to store information about a publicKey and signature that has been registered with a Consent. +This publicKey can be used to verify that transaction authorizations have been signed by the previously-registered privateKey, +which resides on a User's device. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| credentialType | 1 | CredentialType | The type of credential this is - `FIDO` or `GENERIC` | +| status | 1 | CredentialStatus | The current status of the credential. | +| genericPayload | 0..1 | GenericCredential | Required if credentialType is GENERIC. A description of the credential and information which allows the recipient of the credential to test its veracity. | +| fidoPayload | 0..1 | FIDOPublicKeyCredentialAttestation | Required if credentialType is FIDO. A description of the credential and information which allows the recipient of the credential to test its veracity. | + +##### 3.2.1.11 CredentialStatus +The CredentialStatus data type stores the state of a credential request. Its data model is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| CredentialStatus | 1 | Enum of String(1..32) |See [Section 3.2.2.6](#3225-CredentialStatus) below (CredentialStatus) for more information on allowed values. | + +##### 3.2.1.12 DateTime +The DateTime data type used in these definitions is as defined in [Section 7.2.14](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7214-datetime) of Ref. 1 above. +##### 3.2.1.13 ErrorInformation +The ErrorInformation data type used in these definitions is as defined in [Section 7.4.2](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#742-errorinformation) of Ref. 1 above + +Valid values for ErrorCode and ErrorDescription are defined in [Error Codes](#ErrorCodes) + +##### 3.2.1.14 ExtensionList +The ExtensionList data type used in these definitions is as defined in [Section 7.4.4](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#744-extensionlist) of Ref. 1 above. +##### 3.2.1.15 FspId +The FspId data type used in these definitions is as defined in [Section 7.3.16](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7316-fspid) of Ref. 1 above. + +##### 3.2.1.16 GenericCredential +The GenericCredential object stores the payload for a credential which is validated according to a comparison of the signature created from the challenge using a private key against the same challenge signed using a public key. Its content is as follows. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| publicKey | 1 | BinaryString | The public key to be used in checking the signature. | +| signature | 1 | BinaryString | The signature to be checked against the public key. | + +##### 3.2.1.17 Money +The Money type used in these definitions is a defined in [Section 7.4.10](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7410-money) of Ref. 1 above. +##### 3.2.1.18 Note +The Note data type used in these definitions is as defined in [Section 7.3.23](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7323-note) of Ref. 1 above. +##### 3.2.1.19 Party + +The Note data type used in these definitions is as defined in [Section 7.4.11](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7411-party) of Ref. 1 above. + +##### 3.2.1.20 PartyIdInfo +The PartyIdInfo data type used in these definitions is as defined in [Section 7.4.13](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7413-partyidinfo) of Ref. 1 above. + + +##### 3.2.1.21 Scope +The Scope element contains an identifier defining, in the terms of a DFSP, an account on which access types can be requested or granted. It also defines the access types which are requested or granted. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| address | 1 |AccountAddress | The address of the account to which the PISP wishes to be permitted access, or is being granted access | +| actions | 1..32 |ScopeAction | The action that the PISP wants permission to take in relation to the customer’s account, or that it has been granted in relation to the customer’s account| +##### 3.2.1.22 ScopeAction +The ScopeAction element contains an access type which a PISP can request from a DFSP, or which a DFSP can grant to a PISP. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| scopeAction | 1 | Enum of String(1..32)| See [Section 3.2.2.9](#3228-scopeenumeration) below (ScopeEnumeration) for more information on allowed values. | +##### 3.2.1.23 ServiceType +The ServiceType element contains a type of service where the requester wants a list of the participants in the scheme which provide that service. It must be a member of the appropriate enumeration. +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| serviceType | 1 | Enum of String(1..32) | See [Section 3.2.2.10](#3229-servicetype) below (ServiceType) for more information on allowed values. | + +##### 3.2.1.24 TransactionType +The TransactionType type used in these definitions is as defined in [Section 7.4.18](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7418-transactiontype) of Ref. 1 above. +##### 3.2.1.25 TransactionState +The TransactionState type used in these definitions is as defined in [Section 7.3.33](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7333-transactionstate) of Ref. 1 above. +##### 3.2.1.26 Uri +The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. The regular expression for restricting the Uri type is as follows: +`^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? ` +##### 3.2.1.27 FIDOPublicKeyCredentialAttestation + +A data model representing a FIDO Attestation result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAttestationResponse | The attestation response from the authenticator | + +##### 3.2.1.28 FIDOPublicKeyCredentialAssertion + +A data model representing a FIDO Assertion result. Derived from [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential) in [WebAuthN](https://w3c.github.io/webauthn/). + +The `PublicKeyCredential` interface represents the below fields with a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). +For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| id | 1 | String(59..118) | The identifier of a keypair created by an authenticator | +| rawId | 0..1 | String(59..118) | The identifier of a keypair created by an authenticator, base64 encoded | +| response | 1 | AuthenticatorAssertionResponse | The assertion response from the authenticator | + +##### 3.2.1.29 AuthenticatorAttestationResponse + +A data model representing an [AttestationStatement](https://w3c.github.io/webauthn/#attestation-statement) from [WebAuthN](https://w3c.github.io/webauthn/). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| clientDataJSON | 1 | String(121...512) | JSON string with client data | +| attestationObject | 1 | String(306...2048) | Object encoded in Concise Binary Object Representation(CBOR), as defined in [RFC-8949](https://www.rfc-editor.org/rfc/rfc8949)| + +##### 3.2.1.30 AuthenticatorAssertionResponse + +A data model representing an [AuthenticatorAssertionResponse](https://w3c.github.io/webauthn/#authenticatorassertionresponse). + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| authenticatorData | 1 | String(29..256) | Information about the authenticator. | +| clientDataJSON | 1 | String(121..512) | base64 encoded JSON string containing information about the client. | +| signature | 1 | String(59..256) | The signature generated by the private key associated with this credential. | +| userHandle | 0..1 | String(1..88) | This field is optionally provided by the authenticator, and represents the user.id that was supplied during registration, as defined in [WebAuthN's user.id](https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id).| + +##### 3.2.1.31 SignedPayload + +A data model representing a Third Party Transaction request signature. + +| Name | Cardinality | Type | Description | +| --- | --- | --- | --- | +| signedPayloadType | 1 | SignedPayloadType | `FIDO` or `GENERIC` | +| genericSignedPayload | 0..1 | BinaryString(256) | Required if signedPayloadType is of type `GENERIC`. A BinaryString(256) of a signature of a sha-256 hash of the challenge. | +| fidoSignedPayload | 0..1 | FIDOPublicKeyCredentialAssertion | Required if signedPayloadType is of type `FIDO`. | + +### 3.2.2 Enumerations +#### 3.2.2.1 AuthenticationResponse +The AuthenticationResponse enumeration describes the result of authenticating verification request. +| Name | Description | +| --- | ----------- | +| VERIFIED | The challenge was correctly signed. | +| REJECTED | The challenge was not correctly signed. | +#### 3.2.2.2 AuthorizationResponseType +The AuthorizationResponseType enumeration is the same as the AuthorizationResponse enumeration described in [Section 7.5.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#753-authorizationresponse) of Ref. 1 above. +#### 3.2.2.3 ConsentRequestChannelType + +| Name | Description | +| --- | ----------- | +| WEB | DFSP can support authorization via a web-based login | +| OTP | DFSP can support authorization via a One Time PIN | + +#### 3.2.2.4 ConsentStatusType +The ConsentStatusType enumeration describes the allowed status values that a consent item can have. These are as follows: +| Name | Description | +| --- | ----------- | +| ISSUED | The consent has been issued by the DFSP. | +| REVOKED | The consent has been revoked. | + +#### 3.2.2.5 CredentialStatus +This contains the allowed values for the CredentialStatus +| Name | Description | +| --- | ----------- | +| PENDING | The credential has been created but not yet verified. | +| VERIFIED | Authentication service has verified the credential. | + +#### 3.2.2.6 CredentialType +The CredentialType enumeration contains the allowed values for the type of credential which is associated with a permission. +| Name | Description | +| --- | ----------- | +| FIDO | The credential is based on a FIDO challenge. Its payload is a FIDOPublicKeyCredentialAttestation object. | +| GENERIC | The credential is based on a simple public key validation. Its payload is a GenericCredential object | + +#### 3.2.2.7 PartyIdType +The PartyIdType enumeration is extended for PISPs to include a definition for the identifier which represents a link between a specific PISP and an account at a DFSP which a customer has given the PISP permission to access. + +| Name | Description | +| --- | ----------- | +| MSISDN | An MSISDN (Mobile Station International Subscriber Directory Number; that is, a phone number) is used in reference to a Party. The MSISDN identifier should be in international format according to the ITU-T E.16437 standard. Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix.| +| EMAIL | An email is used in reference to a Party. The format of the email should be according to the informational RFC 369638.| +| PERSONAL_ID | A personal identifier is used in reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element.| +| BUSINESS | A specific Business (for example, an organization or a company) is used in reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used.| +| DEVICE | A specific device (for example, POS or ATM) ID connected to a specific business or organization is used in reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element.| +| ACCOUNT_ID | A bank account number or FSP account ID should be used in reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP.| +| IBAN | A bank account number or FSP account ID is used in reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace.| +| ALIAS | An alias is used in reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier.| +| THIRD_PARTY_LINK | A third-party link which represents an agreement between a specific PISP and a customer’s account at a DFSP. The content of the link is created by the DFSP at the time when it gives permission to the PISP for specific access to a given account.| + +#### 3.2.2.8 ScopeEnumeration + +| Name | Description | +| --- | ----------- | +| ACCOUNTS_GET_BALANCE | PISP can request a balance for the linked account | +| ACCOUNTS_TRANSFER | PISP can request a transfer of funds from the linked account in the DFSP | +| ACCOUNTS_STATEMENT | PISP can request a statement of individual transactions on a user’s account | + +#### 3.2.2.9 ServiceType +The ServiceType enumeration describes the types of role for which a DFSP may query using the /services resource. +| Name | Description | +| --- | ----------- | +| THIRD_PARTY_DFSP| DFSPs which will support linking with PISPs | +| PISP | PISPs | +| AUTH_SERVICE | Participants which provide Authentication Services | + +##### 3.2.2.10 SignedPayloadType +The SignedPayloadType enumeration contains the allowed values for the type of a signed payload +| Name | Description | +| --- | ----------- | +| FIDO | The signed payload is based on a FIDO Assertion Response. Its payload is a FIDOPublicKeyCredentialAssertion object. | +| GENERIC | The signed payload is based on a simple public key validation. Its payload is a BinaryString object | + +##### 3.2.2.11 AmountType +See [7.3.1 AmountType](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#731-amounttype) + +##### 3.2.2.12 TransactionRequestState +See [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) + + +## 3.3 Error Codes + +The Third Party API Error Codes are defined in [Section 7.6](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#76-error-codes) of ref 1 above. + +In addition, the Third Party API adds the following error codes, starting with the prefix `6`: + +- General Third Party Error -- **60**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6000** | Third party error | Generic error. | X | X | X | X | X | X | X | X | +| **6001** | Third party request error | Third party request failed. | X | X | X | X | X | X | X | X | +| **6003** | Downstream Failure | The downstream request failed. | X | X | X | X | X | X | X | X | + +- Permission Error -- **61**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6100** | Authentication rejection | Generic authentication rejection | | X | | | | X | | | +| **6101** | Unsupported scopes were requested | PISP requested scopes that the DFSP doesn’t allow/support | | X | X | | | | | | +| **6102** | Consent not granted | User did not grant consent to the PISP | | X | X | | | | | | +| **6103** | Consent not valid | Consent object is not valid or has been revoked | | X | X | | | X | X | X | +| **6104** | Third Party request rejection | The request was rejected | X | X | X | X | X | X | X | X | + +- Validation Error -- **62**_xx_ + +| **Error Code** | **Name** | **Description** | /accounts | /consentRequests | /consents | /parties | /services | /thirdpartyRequests/authorizations | thirdpartyRequests/transactions | thirdpartyRequests/verifications | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **6200** | Invalid Consent Credential | The signature of the credential submitted by the PISP is invalid | | | X | | | | | | +| **6201** | Invalid transaction signature | The signature of the verification response doesn't match the credential | | | | | | X | | X | +| **6203** | Invalid authentication token | DFSP receives invalid authentication token from PISP. | | X | | | | | | | +| **6204** | Bad callbackUri | The callbackUri is deemed invalid or untrustworthy. | | X | | | | | | | +| **6205** | No accounts found | No accounts were found for the given identifier | X | | | | | | | | + diff --git a/vuepress/docs/api/thirdparty/thirdparty-dfsp-v1.0.yaml b/vuepress/docs/api/thirdparty/thirdparty-dfsp-v1.0.yaml new file mode 100644 index 00000000..327d244d --- /dev/null +++ b/vuepress/docs/api/thirdparty/thirdparty-dfsp-v1.0.yaml @@ -0,0 +1,2625 @@ +openapi: 3.0.2 +info: + title: Mojaloop Third Party API (DFSP) + version: '1.0' + description: | + A Mojaloop API for DFSPs supporting Third Party functions. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) to perform actions on behalf of a DFSP's user should implement this API. + PISPs should implement the accompanying API - Mojaloop Third Party API (PISP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: 'The object sent in a `PUT /accounts/{ID}` request.' + properties: + accountList: + description: Information about the accounts that the DFSP associates with the identifier sent by the PISP + type: array + items: + title: Account + type: object + description: Data model for the complex type Account. + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + required: + - accountNickname + - id + - currency + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: The object sent in a `POST /consentRequests` request. + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: Scope + Account Identifier mapping for a Consent. + properties: + address: + title: AccountAddress + type: string + description: | + An address which can be used to identify the account. + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + description: | + The permissions allowed on a given account by a DFSP as defined in + a consent object + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user’s account + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consentRequest. + - "WEB" - The Web auth channel. + - "OTP" - The OTP auth channel. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: 'The object sent in a `PATCH /consentRequests/{ID}` request.' + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /consents: + parameters: + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for resends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1consents/post/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1consents/post/responses/400/headers/Content-Type' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatus + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatus + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: | + The type of the Credential. + - "FIDO" - A FIDO public/private keypair + - "GENERIC" - A Generic public/private keypair + status: + title: CredentialStatus + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/credential/properties/payload' + required: + - credentialType + - status + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + type: string + enum: + - VERIFIED + description: 'The Credential is valid, and ready to be used by the PISP.' + payload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + - payload + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: POST /thirdpartyRequests/authorizations request object. + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer’s account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer’s account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/signedPayloadType' + fidoSignedPayload: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/0/properties/fidoSignedPayload' + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + type: object + properties: + signedPayloadType: + $ref: '#/paths/~1thirdpartyRequests~1verifications/post/requestBody/content/application~1json/schema/oneOf/1/properties/signedPayloadType' + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: The object sent in the POST /thirdpartyRequests/transactions request. + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + $ref: '#/paths/~1accounts~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/accountList/items/properties/currency' + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdPartyRequests/transactions/{ID} request.' + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: 'The object sent in the PATCH /thirdpartyRequests/transactions/{ID} callback.' + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + /thirdpartyRequests/verifications: + parameters: + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + post: + tags: + - thirdpartyRequests + - sampled + operationId: PostThirdpartyRequestsVerifications + summary: PostThirdpartyRequestsVerifications + description: | + The HTTP request `POST /thirdpartyRequests/verifications` is used by the DFSP to verify a third party authorization. + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The thirdparty authorization details to verify + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsVerificationsPostRequestFIDO + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + An object sent in a `PUT /thirdpartyRequests/authorization/{ID}` request. + based mostly on: https://webauthn.guide/#authentication + AuthenticatorAssertionResponse + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - fidoSignedPayload + - title: ThirdpartyRequestsVerificationsPostRequestGeneric + type: object + description: The object sent in the POST /thirdpartyRequests/verifications request. + properties: + verificationRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: Base64 encoded bytes - The challenge generated by the DFSP. + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The id of the stored consent object that contains the credential with which to verify + the signed challenge against. + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - verificationRequestId + - challenge + - consentId + - signedPayloadType + - genericSignedPayload + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyRequestsVerificationsById + summary: GetThirdpartyRequestsVerificationsById + description: | + The HTTP request `/thirdpartyRequests/verifications/{ID}` is used to get + information regarding a previously created or requested authorization. The *{ID}* + in the URI should contain the verification request ID + parameters: + - $ref: '#/paths/~1consents/post/parameters/0' + responses: + '202': + $ref: '#/paths/~1consents/post/responses/202' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsById + summary: PutThirdpartyRequestsVerificationsById + description: | + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}` is used by the Auth-Service to inform + the DFSP of a successful result in validating the verification of a Thirdparty Transaction Request. + + If the validation fails, The Auth-Service MUST use `PUT /thirdpartyRequests/verifications/{ID}/error` + instead. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: The result of validating the Thirdparty Transaction Request + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsVerificationsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdpartyRequests/verifications/{ID} request.' + properties: + authenticationResponse: + type: string + enum: + - VERIFIED + description: The verification passed + required: + - authenticationResponse + example: + authenticationResponse: VERIFIED + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' + '/thirdpartyRequests/verifications/{ID}/error': + parameters: + - $ref: '#/paths/~1accounts~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1consents/parameters/0' + - $ref: '#/paths/~1consents/parameters/1' + - $ref: '#/paths/~1consents/parameters/2' + - $ref: '#/paths/~1consents/parameters/3' + - $ref: '#/paths/~1consents/parameters/4' + - $ref: '#/paths/~1consents/parameters/5' + - $ref: '#/paths/~1consents/parameters/6' + - $ref: '#/paths/~1consents/parameters/7' + - $ref: '#/paths/~1consents/parameters/8' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsVerificationsByIdAndError + summary: PutThirdpartyRequestsVerificationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/verifications/{ID}/error` is used by the Auth-Service to inform + the DFSP of a failure in validating or looking up the verification of a Thirdparty Transaction Request. + parameters: + - $ref: '#/paths/~1consents/post/parameters/1' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1accounts~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1consents/post/responses/400' + '401': + $ref: '#/paths/~1consents/post/responses/401' + '403': + $ref: '#/paths/~1consents/post/responses/403' + '404': + $ref: '#/paths/~1consents/post/responses/404' + '405': + $ref: '#/paths/~1consents/post/responses/405' + '406': + $ref: '#/paths/~1consents/post/responses/406' + '501': + $ref: '#/paths/~1consents/post/responses/501' + '503': + $ref: '#/paths/~1consents/post/responses/503' diff --git a/vuepress/docs/api/thirdparty/thirdparty-pisp-v1.0.yaml b/vuepress/docs/api/thirdparty/thirdparty-pisp-v1.0.yaml new file mode 100644 index 00000000..cb9f52f2 --- /dev/null +++ b/vuepress/docs/api/thirdparty/thirdparty-pisp-v1.0.yaml @@ -0,0 +1,2830 @@ +openapi: 3.0.1 +info: + title: Mojaloop Third Party API (PISP) + version: '1.0' + description: | + A Mojaloop API for Payment Initiation Service Providers (PISPs) to perform Third Party functions on DFSPs' User's accounts. + DFSPs who want to enable Payment Initiation Service Providers (PISPs) should implement the accompanying API - Mojaloop Third Party API (DFSP) instead. + license: + name: Open API for FSP Interoperability (FSPIOP) (Implementation Friendly Version) + url: 'https://github.com/mojaloop/mojaloop-specification/blob/master/LICENSE.md' +servers: + - url: / +paths: + '/accounts/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetAccountsByUserId + summary: GetAccountsByUserId + description: | + The HTTP request `GET /accounts/{ID}` is used to retrieve the list of potential accounts available for linking. + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /accounts/{ID}` is used to return the list of potential accounts available for linking + operationId: UpdateAccountsByUserId + summary: UpdateAccountsByUserId + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: AccountsIDPutResponse + type: object + description: 'The object sent in a `PUT /accounts/{ID}` request.' + properties: + accountList: + description: Information about the accounts that the DFSP associates with the identifier sent by the PISP + type: array + items: + title: Account + type: object + description: Data model for the complex type Account. + properties: + accountNickname: + title: Name + type: string + pattern: '^(?!\s*$)[\w .,''-]{1,128}$' + description: |- + The API data type Name is a JSON String, restricted by a regular expression to avoid characters which are generally not used in a name. + + Regular Expression - The regular expression for restricting the Name type is "^(?!\s*$)[\w .,'-]{1,128}$". The restriction does not allow a string consisting of whitespace only, all Unicode characters are allowed, as well as the period (.) (apostrophe (‘), dash (-), comma (,) and space characters ( ). + + **Note:** In some programming languages, Unicode support must be specifically enabled. For example, if Java is used, the flag UNICODE_CHARACTER_CLASS must be enabled to allow Unicode characters. + address: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items/properties/address' + currency: + title: Currency + description: 'The currency codes defined in [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) as three-letter alphabetic codes are used as the standard naming representation for currencies.' + type: string + minLength: 3 + maxLength: 3 + enum: + - AED + - AFN + - ALL + - AMD + - ANG + - AOA + - ARS + - AUD + - AWG + - AZN + - BAM + - BBD + - BDT + - BGN + - BHD + - BIF + - BMD + - BND + - BOB + - BRL + - BSD + - BTN + - BWP + - BYN + - BZD + - CAD + - CDF + - CHF + - CLP + - CNY + - COP + - CRC + - CUC + - CUP + - CVE + - CZK + - DJF + - DKK + - DOP + - DZD + - EGP + - ERN + - ETB + - EUR + - FJD + - FKP + - GBP + - GEL + - GGP + - GHS + - GIP + - GMD + - GNF + - GTQ + - GYD + - HKD + - HNL + - HRK + - HTG + - HUF + - IDR + - ILS + - IMP + - INR + - IQD + - IRR + - ISK + - JEP + - JMD + - JOD + - JPY + - KES + - KGS + - KHR + - KMF + - KPW + - KRW + - KWD + - KYD + - KZT + - LAK + - LBP + - LKR + - LRD + - LSL + - LYD + - MAD + - MDL + - MGA + - MKD + - MMK + - MNT + - MOP + - MRO + - MUR + - MVR + - MWK + - MXN + - MYR + - MZN + - NAD + - NGN + - NIO + - NOK + - NPR + - NZD + - OMR + - PAB + - PEN + - PGK + - PHP + - PKR + - PLN + - PYG + - QAR + - RON + - RSD + - RUB + - RWF + - SAR + - SBD + - SCR + - SDG + - SEK + - SGD + - SHP + - SLL + - SOS + - SPL + - SRD + - STD + - SVC + - SYP + - SZL + - THB + - TJS + - TMT + - TND + - TOP + - TRY + - TTD + - TVD + - TWD + - TZS + - UAH + - UGX + - USD + - UYU + - UZS + - VEF + - VND + - VUV + - WST + - XAF + - XCD + - XDR + - XOF + - XPF + - XTS + - XXX + - YER + - ZAR + - ZMW + - ZWD + required: + - accountNickname + - id + - currency + required: + - accounts + example: + - accountNickname: dfspa.user.nickname1 + id: dfspa.username.1234 + currency: ZAR + - accountNickname: dfspa.user.nickname2 + id: dfspa.username.5678 + currency: USD + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/accounts/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /accounts/{ID}/error` is used to return error information + operationId: UpdateAccountsByUserIdError + summary: UpdateAccountsByUserIdError + tags: + - accounts + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + title: ErrorInformationObject + type: object + description: Data model for the complex type object that contains ErrorInformation. + properties: + errorInformation: + title: ErrorInformation + type: object + description: Data model for the complex type ErrorInformation. + properties: + errorCode: + title: ErrorCode + type: string + pattern: '^[1-9]\d{3}$' + description: 'The API data type ErrorCode is a JSON String of four characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed. Each error code in the API is a four-digit number, for example, 1234, where the first number (1 in the example) represents the high-level error category, the second number (2 in the example) represents the low-level error category, and the last two numbers (34 in the example) represent the specific error.' + example: '5100' + errorDescription: + title: ErrorDescription + type: string + minLength: 1 + maxLength: 128 + description: Error description string. + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - errorCode + - errorDescription + required: + - errorInformation + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consentRequests: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consentRequests + - sampled + operationId: CreateConsentRequest + summary: CreateConsentRequest + description: | + The HTTP request **POST /consentRequests** is used to request a DFSP to grant access to one or more + accounts owned by a customer of the DFSP for the PISP who sends the request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: The consentRequest to create + required: true + content: + application/json: + schema: + title: ConsentRequestsPostRequest + type: object + description: The object sent in a `POST /consentRequests` request. + properties: + consentRequestId: + title: CorrelationId + type: string + pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' + description: 'Identifier that correlates all messages of the same sequence. The API data type UUID (Universally Unique Identifier) is a JSON String in canonical format, conforming to [RFC 4122](https://tools.ietf.org/html/rfc4122), that is restricted by a regular expression for interoperability reasons. A UUID is always 36 characters long, 32 hexadecimal symbols and 4 dashes (‘-‘).' + example: b51ec534-ee48-4575-b6a9-ead2955b8069 + userId: + type: string + description: 'The identifier used in the **GET /accounts/**_{ID}_. Used by the DFSP to correlate an account lookup to a `consentRequest`' + minLength: 1 + maxLength: 128 + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + title: Scope + type: object + description: Scope + Account Identifier mapping for a Consent. + properties: + address: + title: AccountAddress + type: string + description: | + An address which can be used to identify the account. + pattern: '^([0-9A-Za-z_~\-\.]+[0-9A-Za-z_~\-])$' + minLength: 1 + maxLength: 1023 + actions: + type: array + minItems: 1 + maxItems: 32 + items: + title: ScopeAction + type: string + enum: + - ACCOUNTS_GET_BALANCE + - ACCOUNTS_TRANSFER + - ACCOUNTS_STATEMENT + description: | + The permissions allowed on a given account by a DFSP as defined in + a consent object + - ACCOUNTS_GET_BALANCE: PISP can request a balance for the linked account + - ACCOUNTS_TRANSFER: PISP can request a transfer of funds from the linked account in the DFSP + - ACCOUNTS_STATEMENT: PISP can request a statement of individual transactions on a user’s account + required: + - address + - actions + authChannels: + type: array + minLength: 1 + maxLength: 256 + items: + title: ConsentRequestChannelType + type: string + enum: + - WEB + - OTP + description: | + The auth channel being used for the consentRequest. + - "WEB" - The Web auth channel. + - "OTP" - The OTP auth channel. + callbackUri: + title: Uri + type: string + pattern: '^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?' + minLength: 1 + maxLength: 512 + description: | + The API data type Uri is a JSON string in a canonical format that is restricted by a regular expression for interoperability reasons. + required: + - consentRequestId + - userId + - scopes + - authChannels + - callbackUri + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetConsentRequestsById + summary: GetConsentRequestsById + description: | + The HTTP request `GET /consentRequests/{ID}` is used to get information about a previously + requested consent. The *{ID}* in the URI should contain the consentRequestId that was assigned to the + request by the PISP when the PISP originated the request. + tags: + - consentRequests + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - consentRequests + - sampled + operationId: UpdateConsentRequest + summary: UpdateConsentRequest + description: | + A DFSP uses this callback to (1) inform the PISP that the consentRequest has been accepted, + and (2) communicate to the PISP which `authChannel` it should use to authenticate their user + with. + + When a PISP requests a series of permissions from a DFSP on behalf of a DFSP’s customer, not all + the permissions requested may be granted by the DFSP. Conversely, the out-of-band authorization + process may result in additional privileges being granted by the account holder to the PISP. The + **PUT /consentRequests/**_{ID}_ resource returns the current state of the permissions relating to a + particular authorization request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentRequestsIDPutResponseWeb + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking web flow, + the result is the PISP being instructed on a specific URL where this + supposed user should be redirected. This URL should be a place where + the user can prove their identity (e.g., by logging in). + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeWeb + type: string + enum: + - WEB + description: | + The web auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + authUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + - callbackUri + - authUri + additionalProperties: false + - title: ConsentRequestsIDPutResponseOTP + type: object + description: | + The object sent in a `PUT /consentRequests/{ID}` request. + + Schema used in the request consent phase of the account linking OTP/SMS flow. + properties: + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + authChannels: + type: array + minLength: 1 + maxLength: 1 + items: + title: ConsentRequestChannelTypeOTP + type: string + enum: + - OTP + description: | + The OTP auth channel being used for PUT consentRequest/{ID} request. + callbackUri: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/callbackUri' + required: + - scopes + - authChannels + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + tags: + - consentRequests + - sampled + operationId: PatchConsentRequest + summary: PatchConsentRequest + description: | + After the user completes an out-of-band authorization with the DFSP, the PISP will receive a token which they can use to prove to the DFSP that the user trusts this PISP. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ConsentRequestsIDPatchRequest + type: object + description: 'The object sent in a `PATCH /consentRequests/{ID}` request.' + properties: + authToken: + type: string + pattern: '^[A-Za-z0-9-_]+[=]{0,2}$' + description: 'The API data type BinaryString is a JSON String. The string is a base64url encoding of a string of raw bytes, where padding (character ‘=’) is added at the end of the data if needed to ensure that the string is a multiple of 4 characters. The length restriction indicates the allowed number of characters.' + required: + - authToken + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consentRequests/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consentRequests + operationId: NotifyErrorConsentRequests + summary: NotifyErrorConsentRequests + description: | + DFSP responds to the PISP if something went wrong with validating an OTP or secret. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /consents: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + tags: + - consents + - sampled + operationId: PostConsents + summary: PostConsents + description: | + The **POST /consents** request is used to request the creation of a consent for interactions between a PISP and the DFSP who owns the account which a PISP’s customer wants to allow the PISP access to. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentPostRequestAUTH + type: object + description: | + The object sent in a `POST /consents` request to the Auth-Service + by a DFSP to store registered Consent and credential + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and FSP for the Consent object + determined by the DFSP who creates the Consent. + scopes: + minLength: 1 + maxLength: 256 + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + credential: + allOf: + - $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + - REVOKED - The consent has been revoked + required: + - consentId + - scopes + - credential + - status + additionalProperties: false + - title: ConsentPostRequestPISP + type: object + description: | + The provisional Consent object sent by the DFSP in `POST /consents`. + properties: + consentId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the consent object. The ID + should be reused for resends of the same consent. A new ID should be generated + for each new consent. + consentRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + The ID given to the original consent request on which this consent is based. + scopes: + type: array + minLength: 1 + maxLength: 256 + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents/post/requestBody/content/application~1json/schema/oneOf/0/properties/status' + required: + - consentId + - consentRequestId + - scopes + - status + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The **GET /consents/**_{ID}_ resource allows a party to enquire after the status of a consent. The *{ID}* used in the URI of the request should be the consent request ID which was used to identify the consent when it was created. + tags: + - consents + operationId: GetConsent + summary: GetConsent + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + description: | + The HTTP request `PATCH /consents/{ID}` is used + + - In account linking in the Credential Registration phase. Used by a DFSP + to notify a PISP a credential has been verified and registered with an + Auth service. + + - In account unlinking by a hub hosted auth service and by DFSPs + in non-hub hosted scenarios to notify participants of a consent being revoked. + + Called by a `auth-service` to notify a PISP and DFSP of consent status in hub hosted scenario. + Called by a `DFSP` to notify a PISP of consent status in non-hub hosted scenario. + tags: + - consents + - sampled + operationId: PatchConsentByID + summary: PatchConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPatchResponseVerified + description: | + PATCH /consents/{ID} request object. + + Sent by the DFSP to the PISP when a consent is verified. + Used in the "Register Credential" part of the Account linking flow. + type: object + properties: + credential: + type: object + properties: + status: + title: CredentialStatus + type: string + enum: + - VERIFIED + description: | + The status of the Credential. + - "VERIFIED" - The Credential is valid and verified. + required: + - status + required: + - credential + - title: ConsentsIDPatchResponseRevoked + description: | + PATCH /consents/{ID} request object. + + Sent to both the PISP and DFSP when a consent is revoked. + Used in the "Unlinking" part of the Account Unlinking flow. + type: object + properties: + status: + title: ConsentStatus + type: string + enum: + - REVOKED + description: |- + Allowed values for the enumeration ConsentStatus + - REVOKED - The consent has been revoked + revokedAt: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + required: + - status + - revokedAt + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP and Auth Service. + + - Called by a `PISP` to after signing a challenge. Sent to an DFSP for verification. + - Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + tags: + - consents + - sampled + operationId: PutConsentByID + summary: PutConsentByID + requestBody: + required: true + content: + application/json: + schema: + oneOf: + - title: ConsentsIDPutResponseSigned + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the PISP to update a Consent with a signed challenge and register a credential. + Called by a `PISP` to after signing a challenge. Sent to a DFSP for verification. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + title: ConsentStatus + type: string + enum: + - ISSUED + description: |- + Allowed values for the enumeration ConsentStatus + - ISSUED - The consent has been issued by the DFSP + credential: + title: SignedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + SignedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be PENDING when + updating a credential. + properties: + credentialType: + title: CredentialType + type: string + enum: + - FIDO + - GENERIC + description: | + The type of the Credential. + - "FIDO" - A FIDO public/private keypair + - "GENERIC" - A Generic public/private keypair + status: + title: CredentialStatus + type: string + enum: + - PENDING + description: | + The status of the Credential. + - "PENDING" - The credential has been created, but has not been verified + genericPayload: + title: GenericCredential + type: object + description: | + A publicKey + signature of a challenge for a generic public/private keypair + properties: + publicKey: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + signature: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - publicKey + - signature + additionalProperties: false + fidoPayload: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/credential/properties/payload' + required: + - credentialType + - status + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + - title: ConsentsIDPutResponseVerified + type: object + description: | + The HTTP request `PUT /consents/{ID}` is used by the DFSP or Auth-Service to update a Consent object once it has been Verified. + Called by a `auth-service` to notify a DFSP that a credential has been verified and registered. + properties: + scopes: + type: array + items: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/scopes/items' + status: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/status' + credential: + title: VerifiedCredential + type: object + description: | + A credential used to allow a user to prove their identity and access + to an account with a DFSP. + + VerifiedCredential is a special formatting of the credential to allow us to be + more explicit about the `status` field - it should only ever be VERIFIED when + updating a credential. + properties: + credentialType: + $ref: '#/paths/~1consents~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/0/properties/credential/properties/credentialType' + status: + type: string + enum: + - VERIFIED + description: 'The Credential is valid, and ready to be used by the PISP.' + payload: + title: FIDOPublicKeyCredentialAttestation + type: object + description: | + A data model representing a FIDO Attestation result. Derived from + [`PublicKeyCredential` Interface](https://w3c.github.io/webauthn/#iface-pkcredential). + + The `PublicKeyCredential` interface represents the below fields with + a Type of Javascript [ArrayBuffer](https://heycam.github.io/webidl/#idl-ArrayBuffer). + For this API, we represent ArrayBuffers as base64 encoded utf-8 strings. + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAttestationResponse + properties: + clientDataJSON: + type: string + description: | + JSON string with client data + minLength: 121 + maxLength: 512 + attestationObject: + type: string + description: | + CBOR.encoded attestation object + minLength: 306 + maxLength: 2048 + required: + - clientDataJSON + - attestationObject + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - response + - type + additionalProperties: false + required: + - credentialType + - status + - payload + additionalProperties: false + required: + - scopes + - credential + additionalProperties: false + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + delete: + description: | + Used by PISP, DFSP + + The **DELETE /consents/**_{ID}_ request is used to request the revocation of a previously agreed consent. + For tracing and auditing purposes, the switch should be sure not to delete the consent physically; + instead, information relating to the consent should be marked as deleted and requests relating to the + consent should not be honoured. + operationId: DeleteConsentByID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - consents + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/consents/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - consents + operationId: NotifyErrorConsents + summary: NotifyErrorConsents + description: | + DFSP responds to the PISP if something went wrong with validating or storing consent. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/authorizations: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + description: | + The HTTP request **POST /thirdpartyRequests/authorizations** is used to request the validation by a customer for the transfer described in the request. + operationId: PostThirdpartyRequestsAuthorizations + summary: PostThirdpartyRequestsAuthorizations + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Authorization request details + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsAuthorizationsPostRequest + description: POST /thirdpartyRequests/authorizations request object. + type: object + properties: + authorizationRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + transactionRequestId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + challenge: + type: string + description: The challenge that the PISP's client is to sign + transferAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be debited from the sending customer’s account as a consequence of the transaction. + payeeReceiveAmount: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount that will be credited to the receiving customer’s account as a consequence of the transaction. + fees: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/amount/allOf/0' + description: The amount of fees that the paying customer will be charged as part of the transaction. + payer: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + description: 'Information about the Payer type, id, sub-type/id, FSP Id in the proposed financial transaction.' + payee: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payee/allOf/0' + description: Information about the Payee in the proposed financial transaction. + transactionType: + title: TransactionType + type: object + description: Data model for the complex type TransactionType. + properties: + scenario: + title: TransactionScenario + type: string + enum: + - DEPOSIT + - WITHDRAWAL + - TRANSFER + - PAYMENT + - REFUND + description: |- + Below are the allowed values for the enumeration. + - DEPOSIT - Used for performing a Cash-In (deposit) transaction. In a normal scenario, electronic funds are transferred from a Business account to a Consumer account, and physical cash is given from the Consumer to the Business User. + - WITHDRAWAL - Used for performing a Cash-Out (withdrawal) transaction. In a normal scenario, electronic funds are transferred from a Consumer’s account to a Business account, and physical cash is given from the Business User to the Consumer. + - TRANSFER - Used for performing a P2P (Peer to Peer, or Consumer to Consumer) transaction. + - PAYMENT - Usually used for performing a transaction from a Consumer to a Merchant or Organization, but could also be for a B2B (Business to Business) payment. The transaction could be online for a purchase in an Internet store, in a physical store where both the Consumer and Business User are present, a bill payment, a donation, and so on. + - REFUND - Used for performing a refund of transaction. + example: DEPOSIT + subScenario: + title: TransactionSubScenario + type: string + pattern: '^[A-Z_]{1,32}$' + description: 'Possible sub-scenario, defined locally within the scheme (UndefinedEnum Type).' + example: LOCALLY_DEFINED_SUBSCENARIO + initiator: + title: TransactionInitiator + type: string + enum: + - PAYER + - PAYEE + description: |- + Below are the allowed values for the enumeration. + - PAYER - Sender of funds is initiating the transaction. The account to send from is either owned by the Payer or is connected to the Payer in some way. + - PAYEE - Recipient of the funds is initiating the transaction by sending a transaction request. The Payer must approve the transaction, either automatically by a pre-generated OTP or by pre-approval of the Payee, or by manually approving in his or her own Device. + example: PAYEE + initiatorType: + title: TransactionInitiatorType + type: string + enum: + - CONSUMER + - AGENT + - BUSINESS + - DEVICE + description: |- + Below are the allowed values for the enumeration. + - CONSUMER - Consumer is the initiator of the transaction. + - AGENT - Agent is the initiator of the transaction. + - BUSINESS - Business is the initiator of the transaction. + - DEVICE - Device is the initiator of the transaction. + example: CONSUMER + refundInfo: + title: Refund + type: object + description: Data model for the complex type Refund. + properties: + originalTransactionId: + $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + refundReason: + title: RefundReason + type: string + minLength: 1 + maxLength: 128 + description: Reason for the refund. + example: Free text indicating reason for the refund. + required: + - originalTransactionId + balanceOfPayments: + title: BalanceOfPayments + type: string + pattern: '^[1-9]\d{2}$' + description: '(BopCode) The API data type [BopCode](https://www.imf.org/external/np/sta/bopcode/) is a JSON String of 3 characters, consisting of digits only. Negative numbers are not allowed. A leading zero is not allowed.' + example: '123' + required: + - scenario + - initiator + - initiatorType + expiration: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/completedTimestamp' + description: 'The time by which the transfer must be completed, set by the payee DFSP.' + extensionList: + title: ExtensionList + type: object + description: 'Data model for the complex type ExtensionList. An optional list of extensions, specific to deployment.' + properties: + extension: + type: array + items: + title: Extension + type: object + description: Data model for the complex type Extension. + properties: + key: + title: ExtensionKey + type: string + minLength: 1 + maxLength: 32 + description: Extension key. + value: + title: ExtensionValue + type: string + minLength: 1 + maxLength: 128 + description: Extension value. + required: + - key + - value + minItems: 1 + maxItems: 16 + description: Number of Extension elements. + required: + - extension + required: + - authorizationRequestId + - transactionRequestId + - challenge + - transferAmount + - payeeReceiveAmount + - fees + - payer + - payee + - transactionType + - expiration + additionalProperties: false + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: | + The HTTP request **GET /thirdpartyRequests/authorizations/**_{ID}_ is used to get information relating + to a previously issued authorization request. The *{ID}* in the request should match the + `authorizationRequestId` which was given when the authorization request was created. + operationId: GetThirdpartyRequestsAuthorizationsById + summary: GetThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + After receiving the **POST /thirdpartyRequests/authorizations**, the PISP will present the details of the + transaction to their user, and request that the client sign the `challenge` field using the credential + they previously registered. + + The signed challenge will be sent back by the PISP in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + operationId: PutThirdpartyRequestsAuthorizationsById + summary: PutThirdpartyRequestsAuthorizationsById + tags: + - authorizations + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Signed authorization object + required: true + content: + application/json: + schema: + oneOf: + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer rejected the terms of the transfer. + type: string + enum: + - REJECTED + required: + - responseType + - title: ThirdpartyRequestsAuthorizationsIDPutResponseFIDO + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + title: AuthorizationResponseType + description: | + The customer accepted the terms of the transfer + type: string + enum: + - ACCEPTED + signedPayload: + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeFIDO + type: string + enum: + - FIDO + description: Describes a challenge that has been signed with FIDO Attestation flows + fidoSignedPayload: + title: FIDOPublicKeyCredentialAssertion + type: object + description: | + An object sent in a `PUT /thirdpartyRequests/authorization/{ID}` request. + based mostly on: https://webauthn.guide/#authentication + AuthenticatorAssertionResponse + properties: + id: + type: string + description: | + credential id: identifier of pair of keys, base64 encoded + https://w3c.github.io/webauthn/#ref-for-dom-credential-id + minLength: 59 + maxLength: 118 + rawId: + type: string + description: | + raw credential id: identifier of pair of keys, base64 encoded. + minLength: 59 + maxLength: 118 + response: + type: object + description: | + AuthenticatorAssertionResponse + properties: + authenticatorData: + type: string + description: | + Authenticator data object. + minLength: 49 + maxLength: 256 + clientDataJSON: + type: string + description: | + JSON string with client data. + minLength: 121 + maxLength: 512 + signature: + type: string + description: | + The signature generated by the private key associated with this credential. + minLength: 59 + maxLength: 256 + userHandle: + type: string + description: | + This field is optionally provided by the authenticator, and + represents the user.id that was supplied during registration. + minLength: 1 + maxLength: 88 + required: + - authenticatorData + - clientDataJSON + - signature + additionalProperties: false + type: + type: string + description: 'response type, we need only the type of public-key' + enum: + - public-key + required: + - id + - rawId + - response + - type + additionalProperties: false + required: + - signedPayloadType + - fidoSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + - title: ThirdpartyRequestsAuthorizationsIDPutResponseGeneric + type: object + description: 'The object sent in the PUT /thirdpartyRequests/authorizations/{ID} callback.' + properties: + responseType: + $ref: '#/paths/~1thirdpartyRequests~1authorizations~1%7BID%7D/put/requestBody/content/application~1json/schema/oneOf/1/properties/responseType' + signedPayload: + type: object + properties: + signedPayloadType: + title: SignedPayloadTypeGeneric + type: string + enum: + - GENERIC + description: Describes a challenge that has been signed with a private key + genericSignedPayload: + $ref: '#/paths/~1consentRequests~1%7BID%7D/patch/requestBody/content/application~1json/schema/properties/authToken' + required: + - signedPayloadType + - genericSignedPayload + additionalProperties: false + required: + - responseType + - signedPayload + additionalProperties: false + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/authorizations/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: PutThirdpartyRequestsAuthorizationsByIdAndError + summary: PutThirdpartyRequestsAuthorizationsByIdAndError + description: | + The HTTP request `PUT /thirdpartyRequests/authorizations/{ID}/error` is used by the DFSP or PISP to inform + the other party that something went wrong with a Thirdparty Transaction Authorization Request. + + The PISP may use this to tell the DFSP that the Thirdparty Transaction Authorization Request is invalid or doesn't + match a `transactionRequestId`. + + The DFSP may use this to tell the PISP that the signed challenge returned in `PUT /thirdpartyRequest/authorizations/{ID}` + was invalid. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + /thirdpartyRequests/transactions: + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + post: + operationId: ThirdpartyRequestsTransactionsPost + summary: ThirdpartyRequestsTransactionsPost + description: The HTTP request POST `/thirdpartyRequests/transactions` is used by a PISP to initiate a 3rd party Transaction request with a DFSP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Transaction request to be created. + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsPostRequest + type: object + description: The object sent in the POST /thirdpartyRequests/transactions request. + properties: + transactionRequestId: + allOf: + - $ref: '#/paths/~1consentRequests/post/requestBody/content/application~1json/schema/properties/consentRequestId' + description: | + Common ID between the PISP and the Payer DFSP for the transaction request object. The ID should be reused for resends of the same transaction request. A new ID should be generated for each new transaction request. + payee: + allOf: + - title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0' + merchantClassificationCode: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/merchantClassificationCode' + name: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/name' + personalInfo: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/party/properties/personalInfo' + required: + - partyIdInfo + description: Information about the Payee in the proposed financial transaction. + payer: + allOf: + - title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + - CONSENT + - THIRD_PARTY_LINK + description: | + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory + Number, that is, the phone number) is used as reference to a participant. + The MSISDN identifier should be in international format according to the + [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). + Optionally, the MSISDN may be prefixed by a single plus sign, indicating the + international prefix. + - EMAIL - An email is used as reference to a + participant. The format of the email should be according to the informational + [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. + Examples of personal identification are passport number, birth certificate + number, and national registration number. The identifier number is added in + the PartyIdentifier element. The personal identifier type is added in the + PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) + is used as reference to a participant. The BUSINESS identifier can be in any + format. To make a transaction connected to a specific username or bill number + in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a + specific business or organization is used as reference to a Party. + For referencing a specific device under a specific business or organization, + use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as + reference to a participant. The ACCOUNT_ID identifier can be in any format, + as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a + participant. The IBAN identifier can consist of up to 34 alphanumeric + characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be + created in the FSP as an alternative reference to an account owner. + Another example of an alias is a username in the FSP system. + The ALIAS identifier can be in any format. It is also possible to use the + PartySubIdOrType element for identifying an account under an Alias defined + by the PartyIdentifier. + - CONSENT - A Consent represents an agreement between a PISP, a Customer and + a DFSP which allows the PISP permission to perform actions on behalf of the + customer. A Consent has an authoritative source: either the DFSP who issued + the Consent, or an Auth Service which administers the Consent. + - THIRD_PARTY_LINK - A Third Party Link represents an agreement between a PISP, + a DFSP, and a specific Customer's account at the DFSP. The content of the link + is created by the DFSP at the time when it gives permission to the PISP for + specific access to a given account. + example: PERSONAL_ID + partyIdentifier: + title: PartyIdentifier + type: string + minLength: 1 + maxLength: 128 + description: Identifier of the Party. + example: '16135551212' + partySubIdOrType: + title: PartySubIdOrType + type: string + minLength: 1 + maxLength: 128 + description: 'Either a sub-identifier of a PartyIdentifier, or a sub-type of the PartyIdType, normally a PersonalIdentifierType.' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + description: Information about the Payer in the proposed financial transaction. + amountType: + allOf: + - title: AmountType + type: string + enum: + - SEND + - RECEIVE + description: |- + Below are the allowed values for the enumeration AmountType. + - SEND - Amount the Payer would like to send, that is, the amount that should be withdrawn from the Payer account including any fees. + - RECEIVE - Amount the Payer would like the Payee to receive, that is, the amount that should be sent to the receiver exclusive of any fees. + example: RECEIVE + description: 'SEND for sendAmount, RECEIVE for receiveAmount.' + amount: + allOf: + - title: Money + type: object + description: Data model for the complex type Money. + properties: + currency: + $ref: '#/paths/~1accounts~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/accountList/items/properties/currency' + amount: + title: Amount + type: string + pattern: '^([0]|([1-9][0-9]{0,17}))([.][0-9]{0,3}[1-9])?$' + description: 'The API data type Amount is a JSON String in a canonical format that is restricted by a regular expression for interoperability reasons. This pattern does not allow any trailing zeroes at all, but allows an amount without a minor currency unit. It also only allows four digits in the minor currency unit; a negative value is not allowed. Using more than 18 digits in the major currency unit is not allowed.' + example: '123.45' + required: + - currency + - amount + description: Requested amount to be transferred from the Payer to Payee. + transactionType: + allOf: + - $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/transactionType' + description: Type of transaction. + note: + type: string + minLength: 1 + maxLength: 256 + description: A memo that will be attached to the transaction. + expiration: + type: string + description: | + Date and time until when the transaction request is valid. It can be set to get a quick failure in case the peer FSP takes too long to respond. + example: '2016-05-24T08:38:08.699-04:00' + required: + - transactionRequestId + - payee + - payer + - amountType + - amount + - transactionType + - expiration + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + tags: + - thirdpartyRequests + - sampled + operationId: GetThirdpartyTransactionRequests + summary: GetThirdpartyTransactionRequests + description: | + The HTTP request `GET /thirdpartyRequests/transactions/{ID}` is used to request the + retrieval of a third party transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + tags: + - thirdpartyRequests + - sampled + operationId: UpdateThirdPartyTransactionRequests + summary: UpdateThirdPartyTransactionRequests + description: | + The HTTP request `PUT /thirdpartyRequests/transactions/{ID}` is used by the DFSP to inform the client about + the status of a previously requested thirdparty transaction request. + + Switch(Thirdparty API Adapter) -> PISP + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPutResponse + type: object + description: 'The object sent in the PUT /thirdPartyRequests/transactions/{ID} request.' + properties: + transactionRequestState: + title: TransactionRequestState + type: string + enum: + - RECEIVED + - PENDING + - ACCEPTED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payer FSP has received the transaction from the Payee FSP. + - PENDING - Payer FSP has sent the transaction request to the Payer. + - ACCEPTED - Payer has approved the transaction. + - REJECTED - Payer has rejected the transaction. + example: RECEIVED + required: + - transactionRequestState + example: + transactionRequestState: RECEIVED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + patch: + operationId: NotifyThirdpartyTransactionRequests + summary: NotifyThirdpartyTransactionRequests + description: | + The HTTP request `PATCH /thirdpartyRequests/transactions/{ID}` is used to + notify a thirdparty of the outcome of a transaction request. + + Switch(Thirdparty API Adapter) -> PISP + tags: + - thirdpartyRequests + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ThirdpartyRequestsTransactionsIDPatchResponse + type: object + description: 'The object sent in the PATCH /thirdpartyRequests/transactions/{ID} callback.' + properties: + completedTimestamp: + title: DateTime + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:(\.\d{3}))(?:Z|[+-][01]\d:[0-5]\d)$' + description: 'The API data type DateTime is a JSON String in a lexical format that is restricted by a regular expression for interoperability reasons. The format is according to [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html), expressed in a combined date, time and time zone format. A more readable version of the format is yyyy-MM-ddTHH:mm:ss.SSS[-HH:MM]. Examples are "2016-05-24T08:38:08.699-04:00", "2016-05-24T08:38:08.699Z" (where Z indicates Zulu time zone, same as UTC).' + example: '2016-05-24T08:38:08.699-04:00' + transactionRequestState: + $ref: '#/paths/~1thirdpartyRequests~1transactions~1%7BID%7D/put/requestBody/content/application~1json/schema/properties/transactionRequestState' + transactionState: + title: TransactionState + type: string + enum: + - RECEIVED + - PENDING + - COMPLETED + - REJECTED + description: |- + Below are the allowed values for the enumeration. + - RECEIVED - Payee FSP has received the transaction from the Payer FSP. + - PENDING - Payee FSP has validated the transaction. + - COMPLETED - Payee FSP has successfully performed the transaction. + - REJECTED - Payee FSP has failed to perform the transaction. + example: RECEIVED + required: + - transactionRequestState + - transactionState + example: + transactionRequestState: ACCEPTED + transactionState: COMMITTED + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/thirdpartyRequests/transactions/{ID}/error': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + tags: + - thirdpartyRequests + - sampled + operationId: ThirdpartyTransactionRequestsError + summary: ThirdpartyTransactionRequestsError + description: | + If the server is unable to find the transaction request, or another processing error occurs, + the error callback `PUT /thirdpartyRequests/transactions/{ID}/error` is used. + The `{ID}` in the URI should contain the `transactionRequestId` that was used for the creation of + the thirdparty transaction request. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Error information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}': + parameters: + - name: Type + in: path + required: true + schema: + type: string + description: 'The type of the party identifier. For example, `MSISDN`, `PERSONAL_ID`.' + - name: ID + in: path + required: true + schema: + type: string + description: The identifier value. + - name: Content-Type + in: header + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + - name: Date + in: header + schema: + type: string + required: true + description: The `Date` header field indicates the date when the request was sent. + - name: X-Forwarded-For + in: header + schema: + type: string + required: false + description: |- + The `X-Forwarded-For` header field is an unofficially accepted standard used for informational purposes of the originating client IP address, as a request might pass multiple proxies, firewalls, and so on. Multiple `X-Forwarded-For` values should be expected and supported by implementers of the API. + + **Note:** An alternative to `X-Forwarded-For` is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239). However, to this point RFC 7239 is less-used and supported than `X-Forwarded-For`. + - name: FSPIOP-Source + in: header + schema: + type: string + required: true + description: The `FSPIOP-Source` header field is a non-HTTP standard field used by the API for identifying the sender of the HTTP request. The field should be set by the original sender of the request. Required for routing and signature verification (see header field `FSPIOP-Signature`). + - name: FSPIOP-Destination + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-Destination` header field is a non-HTTP standard field used by the API for HTTP header based routing of requests and responses to the destination. The field must be set by the original sender of the request if the destination is known (valid for all services except GET /parties) so that any entities between the client and the server do not need to parse the payload for routing purposes. If the destination is not known (valid for service GET /parties), the field should be left empty.' + - name: FSPIOP-Encryption + in: header + schema: + type: string + required: false + description: The `FSPIOP-Encryption` header field is a non-HTTP standard field used by the API for applying end-to-end encryption of the request. + - name: FSPIOP-Signature + in: header + schema: + type: string + required: false + description: The `FSPIOP-Signature` header field is a non-HTTP standard field used by the API for applying an end-to-end request signature. + - name: FSPIOP-URI + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-URI` header field is a non-HTTP standard field used by the API for signature verification, should contain the service URI. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + - name: FSPIOP-HTTP-Method + in: header + schema: + type: string + required: false + description: 'The `FSPIOP-HTTP-Method` header field is a non-HTTP standard field used by the API for signature verification, should contain the service HTTP method. Required if signature verification is used, for more information, see [the API Signature document](https://github.com/mojaloop/docs/tree/master/Specification%20Document%20Set).' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesByTypeAndID + parameters: + - name: Accept + in: header + required: true + schema: + type: string + description: The `Accept` header field indicates the version of the API the client would like the server to use. + responses: + '202': + description: Accepted + '400': + description: Bad Request + content: + application/json: + schema: + title: ErrorInformationResponse + type: object + description: Data model for the complex type object that contains an optional element ErrorInformation used along with 4xx and 5xx responses. + properties: + errorInformation: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema/properties/errorInformation' + headers: + Content-Length: + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + Content-Type: + schema: + type: string + required: true + description: The `Content-Type` header indicates the specific version of the API used to send the payload body. + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '405': + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '406': + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '501': + description: Not Implemented + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + '503': + description: Service Unavailable + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/content/application~1json/schema' + headers: + Content-Length: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Length' + Content-Type: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400/headers/Content-Type' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesByTypeAndID2 + parameters: + - name: Content-Length + in: header + required: false + schema: + type: integer + description: |- + The `Content-Length` header field indicates the anticipated size of the payload body. Only sent if there is a body. + + **Note:** The API supports a maximum size of 5242880 bytes (5 Megabytes). + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + title: PartiesTypeIDPutResponse + type: object + description: 'The object sent in the PUT /parties/{Type}/{ID} callback.' + properties: + party: + title: Party + type: object + description: Data model for the complex type Party. + properties: + partyIdInfo: + title: PartyIdInfo + type: object + description: Data model for the complex type PartyIdInfo. An ExtensionList element has been added to this reqeust in version v1.1 + properties: + partyIdType: + title: PartyIdType + type: string + enum: + - MSISDN + - EMAIL + - PERSONAL_ID + - BUSINESS + - DEVICE + - ACCOUNT_ID + - IBAN + - ALIAS + description: |- + Below are the allowed values for the enumeration. + - MSISDN - An MSISDN (Mobile Station International Subscriber Directory Number, that is, the phone number) is used as reference to a participant. The MSISDN identifier should be in international format according to the [ITU-T E.164 standard](https://www.itu.int/rec/T-REC-E.164/en). Optionally, the MSISDN may be prefixed by a single plus sign, indicating the international prefix. + - EMAIL - An email is used as reference to a participant. The format of the email should be according to the informational [RFC 3696](https://tools.ietf.org/html/rfc3696). + - PERSONAL_ID - A personal identifier is used as reference to a participant. Examples of personal identification are passport number, birth certificate number, and national registration number. The identifier number is added in the PartyIdentifier element. The personal identifier type is added in the PartySubIdOrType element. + - BUSINESS - A specific Business (for example, an organization or a company) is used as reference to a participant. The BUSINESS identifier can be in any format. To make a transaction connected to a specific username or bill number in a Business, the PartySubIdOrType element should be used. + - DEVICE - A specific device (for example, a POS or ATM) ID connected to a specific business or organization is used as reference to a Party. For referencing a specific device under a specific business or organization, use the PartySubIdOrType element. + - ACCOUNT_ID - A bank account number or FSP account ID should be used as reference to a participant. The ACCOUNT_ID identifier can be in any format, as formats can greatly differ depending on country and FSP. + - IBAN - A bank account number or FSP account ID is used as reference to a participant. The IBAN identifier can consist of up to 34 alphanumeric characters and should be entered without whitespace. + - ALIAS An alias is used as reference to a participant. The alias should be created in the FSP as an alternative reference to an account owner. Another example of an alias is a username in the FSP system. The ALIAS identifier can be in any format. It is also possible to use the PartySubIdOrType element for identifying an account under an Alias defined by the PartyIdentifier. + partyIdentifier: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partyIdentifier' + partySubIdOrType: + $ref: '#/paths/~1thirdpartyRequests~1transactions/post/requestBody/content/application~1json/schema/properties/payer/allOf/0/properties/partySubIdOrType' + fspId: + $ref: '#/paths/~1services~1%7BServiceType%7D/put/requestBody/content/application~1json/schema/properties/providers/items' + extensionList: + $ref: '#/paths/~1thirdpartyRequests~1authorizations/post/requestBody/content/application~1json/schema/properties/extensionList' + required: + - partyIdType + - partyIdentifier + merchantClassificationCode: + title: MerchantClassificationCode + type: string + pattern: '^[\d]{1,4}$' + description: 'A limited set of pre-defined numbers. This list would be a limited set of numbers identifying a set of popular merchant types like School Fees, Pubs and Restaurants, Groceries, etc.' + name: + title: PartyName + type: string + minLength: 1 + maxLength: 128 + description: Name of the Party. Could be a real name or a nickname. + personalInfo: + title: PartyPersonalInfo + type: object + description: Data model for the complex type PartyPersonalInfo. + properties: + complexName: + title: PartyComplexName + type: object + description: Data model for the complex type PartyComplexName. + properties: + firstName: + title: FirstName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: First name of the Party (Name Type). + example: Henrik + middleName: + title: MiddleName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Middle name of the Party (Name Type). + example: Johannes + lastName: + title: LastName + type: string + minLength: 1 + maxLength: 128 + pattern: '^(?!\s*$)[\p{L}\p{gc=Mark}\p{digit}\p{gc=Connector_Punctuation}\p{Join_Control} .,''''-]{1,128}$' + description: Last name of the Party (Name Type). + example: Karlsson + dateOfBirth: + title: DateofBirth (type Date) + type: string + pattern: '^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)$' + description: Date of Birth of the Party. + example: '1966-06-16' + required: + - partyIdInfo + required: + - party + responses: + '200': + description: OK + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubI}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}': + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - name: SubId + in: path + required: true + schema: + type: string + description: 'A sub-identifier of the party identifier, or a sub-type of the party identifier''s type. For example, `PASSPORT`, `DRIVING_LICENSE`.' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + description: 'The HTTP request `GET /parties/{Type}/{ID}` (or `GET /parties/{Type}/{ID}/{SubId}`) is used to look up information regarding the requested Party, defined by `{Type}`, `{ID}` and optionally `{SubId}` (for example, `GET /parties/MSISDN/123456789`, or `GET /parties/BUSINESS/shoecompany/employee1`).' + summary: Look up party information + tags: + - parties + operationId: PartiesSubIdByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: 'The callback `PUT /parties/{Type}/{ID}` (or `PUT /parties/{Type}/{ID}/{SubId}`) is used to inform the client of a successful result of the Party information lookup.' + summary: Return party information + tags: + - parties + operationId: PartiesSubIdByTypeAndIDPut + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Party information returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/parties/{Type}/{ID}/{SubId}/error': + put: + description: 'If the server is unable to find Party information of the provided identity, or another processing error occurred, the error callback `PUT /parties/{Type}/{ID}/error` (or `PUT /parties/{Type}/{ID}/{SubId}/error`) is used.' + summary: Return party information error + tags: + - parties + operationId: PartiesSubIdErrorByTypeAndID + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/1' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D~1%7BSubId%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}': + parameters: + - name: ServiceType + in: path + required: true + schema: + type: string + description: 'The type of the service identifier. For example, `THIRD_PARTY_DFSP`' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + get: + operationId: GetServicesByServiceType + summary: GetServicesByServiceType + description: | + The HTTP request `GET /services/{ServiceType}` is used to retrieve the list of participants + that support a specified service. + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/parameters/0' + tags: + - services + - sampled + responses: + '202': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/202' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + put: + description: | + The HTTP request `PUT /services/{ServiceType}` is used to return list of participants + that support a specified service. + operationId: PutServicesByServiceType + summary: PutServicesByServiceType + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + required: true + content: + application/json: + schema: + title: ServicesServiceTypePutResponse + type: object + description: 'The object sent in a `PUT /services/{ServiceType}` request.' + properties: + providers: + type: array + minLength: 0 + maxLength: 256 + items: + title: FspId + type: string + minLength: 1 + maxLength: 32 + description: FSP identifier. + required: + - providers + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' + '/services/{ServiceType}/error': + parameters: + - $ref: '#/paths/~1services~1%7BServiceType%7D/parameters/0' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/2' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/3' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/4' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/5' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/6' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/7' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/8' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/9' + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/parameters/10' + put: + description: | + The HTTP request `PUT /services/{ServiceType}/error` is used to return error information + operationId: PutServicesByServiceTypeAndError + summary: PutServicesByServiceTypeAndError + tags: + - services + - sampled + parameters: + - $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/parameters/0' + requestBody: + description: Details of the error returned. + required: true + content: + application/json: + schema: + $ref: '#/paths/~1accounts~1%7BID%7D~1error/put/requestBody/content/application~1json/schema' + responses: + '200': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/put/responses/200' + '400': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/400' + '401': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/401' + '403': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/403' + '404': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/404' + '405': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/405' + '406': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/406' + '501': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/501' + '503': + $ref: '#/paths/~1parties~1%7BType%7D~1%7BID%7D/get/responses/503' diff --git a/vuepress/docs/api/thirdparty/transaction-patterns-linking.md b/vuepress/docs/api/thirdparty/transaction-patterns-linking.md new file mode 100644 index 00000000..7e317db8 --- /dev/null +++ b/vuepress/docs/api/thirdparty/transaction-patterns-linking.md @@ -0,0 +1,412 @@ + +# Transaction Patterns - Linking + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Linking](#Linking) + 3.1 [Pre-linking](#Pre-linking) + 3.2 [Discovery](#Discovery) + 3.3 [Request consent](#Requestconsent) + 3.4 [Authentication](#Authentication) + 3.5 [Grant consent](#Grantconsent) + 3.6 [Credential registration](#Credentialregistration) +4. [Unlinking](#Unlinking) + 4.1 [Unlinking without a Switch Hosted Auth Service](#UnlinkingwithoutaSwitchHostedAuthService) + 4.2 [Unlinking with a Switch Hosted Auth Service](#UnlinkingwithaSwitchHostedAuthService) +5. [Error Scenarios](#ErrorScenarios) + 5.1 [Discovery](#Discovery-1) + 5.2 [Bad consentRequests](#BadconsentRequests) + 5.3 [Authentication](#Authentication-1) + 5.4 [Grant consent](#Grantconsent-1) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the establishment of a relationship between a User, a DFSP and a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Linking + +The goal of the linking process is to explain how users establish trust between +all three interested parties: + +1. User +2. DFSP where User has an account +3. PISP that User wants to rely on to initiate payments + +Linking is broken down into several separate phases: + +1. **Pre-linking** + In this phase, a PISP asks what DFSPs are available to link with. +2. **Request consent** + In this phase, a PISP attempts to establish trust between the 3 parties. +3. **Authentication** + In this phase, a User proves their identity to their DFSP. +4. **Grant consent** + In this phase, a PISP proves to the DFSP that the User and PISP have + established trust and, as a result, the DFSP confirms that mutual trust + exists between the 3 parties. +5. **Credential registration** + In this phase, a User establishes the credential they'll use to consent to + future transfers from the DFSP and initiated by the PISP. + +## 3.1 Pre-linking + +In this phase, a PISP Server needs to know what DFSPs are available to link +with. This is *unlikely* to be done on-demand (e.g., when a User clicks "link" +in the PISP mobile App), and far more likely to be done periodically and cached +by the PISP Server. The reason for this is simply that new DFSPs don't typically +join the Mojaloop network all that frequently, so calling this multiple times on +the same day would likely yield the same results. We recommend that the PISP +calls this request once per day to keep the list of available DFSPs up to date. + +The end-goal of this phase is for the PISP Server to have a final list of DFSPs +available and any relevant metadata about those DFPSs that are necessary to +begin the linking process. + +The PISP can display this list of DFSPs to their user, and the user can select +which DFSP they hold an account with for linking. + +![Pre-linking](./assets/diagrams/linking/0-pre-linking.svg) + +## 3.2 Discovery + +In this phase, we ask the user to select the type and value of identifier they use +with the DFSP they intend to link with. This could be a username, MSISDN (phone number), +or email address. + +The result of this phase is a list of potential accounts available for linking. +The user will then choose one or more of these source accounts and the PISP will +provide these to the DFSP when requesting consent. + +The DFSP MAY send back an `accountNickname` to the PISP in the list of accounts. This list +will be displayed to the user in the PISP application for them to select which accounts +they wish to link. A DFSP could obfuscate some of the nickname depending on their requirements +for displaying account information without authorizing the user. + +**NOTE:** When using the Web authentication channel, it's possible that the +choices made (i.e., the accounts to link with) will be overridden by the user in +a web view. In other words, the user may decide during the Authentication phase +that they actually would like to link a different account than those chosen at +the very beginning. This is perfectly acceptable and should be expected from +time to time. + +![Discovery](./assets/diagrams/linking/1-discovery.svg) + +## 3.3 Request consent + +In this phase, a PISP is asking a specific DFSP to start the process of +establishing consent between three parties: + +1. The PISP +2. The specified DFSP +3. A User that is presumed to be a customer of the DFSP in (2) + +The PISPs request to establish consent must include a few important pieces of +information: + +- The authentication channels that are acceptable to the User +- The scopes required as part of the consent (in this case, almost always just + the ability to view a balance of a specific account and send funds from an + account). + +Some information depends on the authentication channel used (either Web or OTP). +Specifically, if the web authentication channel is used, the following extra +information is required: + +- A callback URI of where a user can be redirected with any extra information. + +The end result of this phase depends on the authentication channel used: + +### 3.3.1 Web + +In the web authentication channel, the result is the PISP being instructed on +a specific URL where this supposed user should be redirected. This URL should be +a place where the user can prove their identity (e.g., by logging in). + +![Request consent](./assets/diagrams/linking/2-request-consent-web.svg) + +### 3.3.2 OTP / SMS + +In the OTP authentication channel, the DFSP sends an 'out of bound' OTP message +to their user (e.g. over SMS or Email). The PISP prompts the user for this OTP +message, and includes it in the `authToken` field in the **PATCH /consentRequests/**_{ID}_ +callback. + +![Request consent](./assets/diagrams/linking/2-request-consent-otp.svg) + +## 3.4 Authentication + +In the authentication phase, the user is expected to prove their identity to the +DFSP. Once this is done, the DFSP will provide the User with some sort of secret +(e.g., an OTP or access token). This secret will then be passed along to the +PISP so that the PISP can demonstrate a chain of trust: + +- The DFSP trusts the User +- The DFSP gives the User a secret +- The User trusts the PISP +- The User gives the PISP the secret that came from the DFSP +- The PISP gives the secret to the DFSP +- The DFSP verified that the secret is correct + +This chain results in the conclusion: The DFSP can trust the PISP is acting on +behalf of the User, and mutual trust exists between all three parties. + +The process of establishing this chain of trust depends on the authentication +channel being used: + +### 3.4.1 Web + +In the web authentication channel, the PISP uses the `authUri` field from +the **PUT /consentRequests/**_{ID}_ callback to redirect the user to the DFSP's +website where they can prove their identity (likely by a typical username and +password style login). + + +**Note:** Keep in mind that at this stage, the User may update their choices of +which accounts to link with. The result of this will be seen later on when +during the Grant consent phase, where the DFSP will provide the correct values +to the PISP in the `scopes` field. + +![Authentication (Web)](./assets/diagrams/linking/3-authentication-web.svg) + + +### 3.4.2 OTP + +When using the OTP authentication channel, the DFSP will send the User some sort +of one-time password over a pre-established channel (such as SMS). The PISP +should prompt the user for this one-time password and then provide it back +to the DFSP using the API call **PATCH /consentRequests/**_{ID}_. + +![Authentication (OTP)](./assets/diagrams/linking/3-authentication-otp.svg) +## 3.5 Grant consent + +Now that mutual trust has been established between all three parties, the DFSP +is able to create a record of that fact by creating a new Consent resource. +This resource will store all the relevant information about the relationship +between the three parties, and will eventually contain additional information +for how the User can prove that it consents to each individual transfer in the +future. + +This phase consists exclusively of the DFSP requesting that a new consent be +created. + +![Grant consent](./assets/diagrams/linking/4-grant-consent.svg) + + +## 3.6 Credential registration + +Once the consent resource has been created, the PISP will attempt to establish +with the DFSP the credential that should be used to verify that a user has +given consent for each transfer in the future. + +This will be done by storing a FIDO credential (e.g., a public key) on the Auth +service inside the consent resource. When future transfers are proposed, we will +require that those transfers be digitally signed by the FIDO credential (in this +case, the private key) in order to be considered valid. + +This credential registration is composed of three phases: (1) deriving the +challenge, (2) registering the credential, and (3) finalizing the consent. + +### 3.6.1 Deriving the challenge + +The PISP must derive the challenge to be used as an input to the FIDO Key +Registration step. This challenge must not be guessable ahead of time by +the PISP. + + +1. _Let `consentId` be the value of the `body.consentId` in the **POST /consents** request_ +2. _Let `scopes` be the value of `body.scopes` in the **POST /consents** request_ + +3. The PISP must build the JSON object `rawChallenge` +``` +{ + "consentId": , + "scopes": +} +``` + +4. Next, the PISP must convert this json object to a string representation using a [RFC-8785 Canonical JSON format](https://tools.ietf.org/html/rfc8785) + +5. Finally, the PISP must calculate a SHA-256 hash of the canonicalized JSON string. +i.e. `SHA256(CJSON(rawChallenge))` + +The output of this algorithm, `challenge` will be used as the challenge for the [FIDO registration flow](https://webauthn.guide/#registration) + + +### 3.6.2 Registering the credential + +Once the PISP has derived the challenge, the PISP will generate a new +credential on the device, digitally signing the challenge, and provide additional +information about the credential on the Consent resource: + +1. The `PublicKeyCredential` object - which contains the key's Id, and an [AuthenticatorAttestationResponse](https://w3c.github.io/webauthn/#iface-authenticatorattestationresponse) which contains the public key +2. A `credentialType` field set to `FIDO` +3. A `status` field set to `PENDING` + +> **Note:** Generic `Credential` objects +> While we are focused on FIDO first, we don't want to exclude PISPs who want +> to offer services to users over other channels, eg. USSD or SMS, for this +> reason, the API also supports a `GENERIC` Credential type, i.e.: +>``` +> CredentialTypeGeneric { +> credentialType: 'GENERIC' +> status: 'PENDING', +> payload: { +> publicKey: base64(...), +> signature: base64(...), +> } +> } +>``` + +The DFSP receives the **PUT /consents/**_{ID}_ call from the PISP, and optionally +validates the Credential object included in the request body. The DFSP then +asks the Auth-Service to create the `Consent` object, and validate the Credential. + +If the DFSP receives a **PUT /consents/**_{ID}_ callback from the Auth-Service, with a +`credential.status` of `VERIFIED`, it knows that the credential is valid according +to the Auth Service. + +Otherwise, if it receives a **PUT /consents/**_{ID}_**/error** callback, it knows that something +went wrong with registering the Consent and associated credential, and can inform +the PISP accordingly. + + +The Auth service is then responsible for calling **POST /participants/CONSENTS/**_{ID}_. +This call will associate the `consentId` with the auth-service's `participantId` and +allows us to look up the Auth service given a `consentId` at a later date. + +![Credential registration: Register](./assets/diagrams/linking/5a-credential-registration.svg) + + +### 3.6.3 Finalizing the Consent + +Once the DFSP is satisfied that the credential is valid, it calls +**POST /participants/THIRD_PARTY_LINK/**_{ID}_ for each account in the +`Consent.scopes` list. This entry is a representation of the account +link between the PISP and DFSP, which the PISP can use to specify +the _source of funds_ for the transaction request. + +Finally, the DFSP calls **PUT /consent/**_{ID}_ with the finalized Consent +object it received from the Auth Service. + + +![Credential registration: Finalize](./assets/diagrams/linking/5b-finalize_consent.svg) + + +# 4. Unlinking + +At some point in the future, it's possible that a User, PISP, or DFSP may decide +that the relationship of trust previously established should no longer exist. +For example, a very common scenario might be a user losing their mobile device +and using an interface from their DFSP to remove the link between the lost +device, the PISP, and the DFSP. + +To make this work, we simply need to provide a way for a member on the network +to remove the Consent resource and notify the other parties about the removal. + + +There are 2 scenarios we need to cater for with a **DELETE /consents/**_{ID}_ request: +1. A DFSP-hosted Auth Service, where no details about the Consent are stored in the Switch, and +2. A Switch hosted Auth Service, where the Switch hosted auth service is considered the Authoritative source on the `Consent` object + + +## 4.1 Unlinking without a Switch Hosted Auth Service +In this case, the switch passes on the **DELETE /consents/22222222-0000-0000-0000-000000000000** request to the DFSP in the `FSPIOP-Destination` header. + +![Unlinking-DFSP-Hosted](./assets/diagrams/linking/6a-unlinking-dfsp-hosted.svg) + +In the case where Unlinking is requested from the DFSP's side, the DFSP can +simply call **PATCH /consents/22222222-0000-0000-0000-000000000000** to inform the PISP of an update to the +`Consent` object. + +## 4.2 Unlinking with a Switch Hosted Auth Service + +In this instance, the PISP still addresses it's **DELETE /consents/22222222-0000-0000-0000-000000000000** call to the +DFSP in the `FSPIOP-Destination` header. + +Internally, the switch will lookup the Authoritative source of the `Consent` object, +using the ALS Call, **GET /participants/CONSENT/**_{ID}_. If it is determined that there +is a Switch hosted Auth Service which 'owns' this `Consent`, the HTTP call **DELETE /consents/**_{ID}_ +will be redirected to the Auth Service. + +![Unlinking-Switch-Hosted](./assets/diagrams/linking/6b-unlinking-hub-hosted.svg) + +# 5.Error Scenarios + +## 5.1 Discovery + +When the DFSP is unable to find a user for the identifier in **GET /accounts/**_{ID}_, +the DFSP responds with error code `6205` in **PUT /accounts/**_{ID}_**/error**. + +![Accounts error](./assets/diagrams/linking/error_scenarios/1-discovery-error.svg) + +## 5.2 ConsentRequest Errors +When the DFSP receives the **POST /consentRequests** request from the PISP, the following processing errors +could occur: + +1. DFSP does not support the specified scopes: `6101`. For example, the `userId` specified does not match the specified accounts, or the `scope.actions` field contains permissions that this DFSP does not support. +2. The PISP sent a bad callbackUri: `6204`. For example, the scheme of the callbackUri could be http, which +the DFSP may choose to not trust. +3. Any other checks or validation of the consentRequests on the DFSP's side fail: `6104`. For example, the user's account may be inactive or suspended. + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /consentRequests/**_{ID}_**/error** callback to the PISP. + +![consentRequests error](./assets/diagrams/linking/error_scenarios/2-request-consent-error.svg) + +## 5.3 Authentication + +When a PISP sends a **PATCH /consentRequests/**_{ID}_ to the DFSP, the `authToken` may be expired or invalid: + +![Authentication Invalid OTP](./assets/diagrams/linking/error_scenarios/3-authentication-otp-invalid.svg) diff --git a/vuepress/docs/api/thirdparty/transaction-patterns-transfer.md b/vuepress/docs/api/thirdparty/transaction-patterns-transfer.md new file mode 100644 index 00000000..2b46f3c0 --- /dev/null +++ b/vuepress/docs/api/thirdparty/transaction-patterns-transfer.md @@ -0,0 +1,380 @@ +# Transaction Patterns - Transfer + +Mojaloop Third Party API + +### Table Of Contents + +1. [Preface](#Preface) + 1.1 [Conventions Used in This Document](#ConventionsUsedinThisDocument) + 1.2 [Document Version Information](#DocumentVersionInformation) + 1.3 [References](#References) +2. [Introduction](#Introduction) + 2.1 [Third Party API Specification](#ThirdPartyAPISpecification) +3. [Transfers](#Transfers) + 3.1 [Discovery](#Discovery) + 3.2 [Agreement](#Agreement) + 3.3 [Transfer](#Transfer) +4. [Request TransactionRequest Status](#RequestTransactionRequestStatus) +5. [Error Conditions](#ErrorConditions) + 5.1 [Bad Payee Lookup](#badpayeelookup) + 5.2 [Bad Thirdparty Transaction Request](#badtptr) + 5.3 [Downstream FSPIOP-API Failure](#downstreamapifailure) + 5.4 [Invalid Signed Challenge](#invalidsignedchallenge) + 5.5 [Thirdparty Transaction Request Timeout](#thirdpartytransactionrequesttimeout) +6. [Appendix](#Appendix) + 6.1 [Deriving the Challenge](#DerivingtheChallenge) + +# 1. Preface + +This section contains information about how to use this document. + +## 1.1. Conventions Used in This Document + +The following conventions are used in this document to identify the +specified types of information. + +|Type of Information|Convention|Example| +|---|---|---| +|**Elements of the API, such as resources**|Boldface|**/authorization**| +|**Variables**|Italics with in angle brackets|_{ID}_| +|**Glossary terms**|Italics on first occurrence; defined in _Glossary_|The purpose of the API is to enable interoperable financial transactions between a _Payer_ (a payer of electronic funds in a payment transaction) located in one _FSP_ (an entity that provides a digital financial service to an end user) and a _Payee_ (a recipient of electronic funds in a payment transaction) located in another FSP.| +|**Library documents**|Italics|User information should, in general, not be used by API deployments; the security measures detailed in _API Signature and API Encryption_ should be used instead.| + +## 1.2. Document Version Information + +| Version | Date | Change Description | +| --- | --- | --- | +| **1.0** | 2021-10-03 | Initial Version + +## 1.3. References + +The following references are used in this specification: + +| Reference | Description | Version | Link | +| --- | --- | --- | --- | +| Ref. 1 | Open API for FSP Interoperability | `1.1` | [API Definition v1.1](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md)| + + +# 2. Introduction + +This document introduces the transaction patterns supported by the Third Party API relating +to the initiation of a Transaction Request from a PISP. + +The API design and architectural style of this API are based on [Section 3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#3-api-definition) of Ref 1. above. + +## 2.1 Third Party API Specification + +The Mojaloop Third Party API Specification includes the following documents: + +- [Data Models](./data-models.md) +- [Transaction Patterns - Linking](./transaction-patterns-linking.md) +- [Transaction Patterns - Transfer](./transaction-patterns-transfer.md) +- [Third Party Open API Definition - DFSP](./thirdparty-dfsp-v1.0.yaml) +- [Third Party Open API Definition - PISP](./thirdparty-dfsp-v1.0.yaml) + + +# 3. Transfers + +Transfers is broken down into the separate sections: +1. **Discovery**: PISP looks up the Payee Party to send funds to + +2. **Agreement** PISP confirms the Payee Party, and looks up the terms of the transaction. If the User accepts the terms of the transaction, they sign the transaction with the credential established in the Linking API flow + +3. **Transfer** The Payer DFSP initiates the transaction, and informs the PISP of the transaction result. + +## 3.1 Discovery + +In this phase, a user enters the identifier of the user they wish to send funds to. The PISP executes a **GET /parties/**_{Type}/{ID}_** (or **GET /parties/**_{Type}/{ID}/{SubId}_) call and awaits a callback from the Mojaloop switch. [Section 6.3](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#63-api-resource-parties) +of Ref 1. above describes the **/parties** resource in detail. + +If the **GET /parties/**_{Type}/{ID}_ request is successful, the PISP will receive a **PUT /parties** callback from the Mojaloop switch. The PISP then confirms the Payee with their user. + +Should the PISP receive a **PUT /parties/**_{Type}/{ID}_**/error** (or **PUT /parties/**_{Type}/{ID}/{SubId}_**/error**) callback, the PISP should display the relevant error to their user. + + + +![Discovery](./assets/diagrams/transfer/1-1-discovery.svg) + +## 3.2 Agreement + +### 3.2.1 Thirdparty Transaction Request + +Upon confirming the details of the Payee with their user, the PISP asks the user to enter the `amount` of funds they wish to send to the Payee, and whether or not they wish the Payee to _receive_ that amount, or they wish to _send_ that amount (`amountType` field). + +If the User has linked more than 1 account with the PISP application, the PISP application can ask the user to choose an account they wish to send funds from. Upon confirming the _source of funds_ account, the PISP can determine: +1. the `FSPIOP-Destination` as the DFSP who the User's account is linked with +2. The `payer` field of the **POST /thirdpartyRequests/transactions** request body. The `partyIdType` is `THIRD_PARTY_LINK`, the `fspId` is the fspId of the DFSP who issued the link, and the `partyIdentifier` is the `accountId` specified in the **POST /consents#scopes** body. + +> See [Grant Consent](./transaction-patterns-linking.md#Grantconsent) for more information. + +The PISP then generates a random `transactionRequestId` of type UUID (see [RFC 4122 UUID](https://tools.ietf.org/html/rfc4122)). + +![1-2-1-agreement](./assets/diagrams/transfer/1-2-1-agreement.svg) + +Upon receiving the **POST /thirdpartyRequests/transactions** call from the PISP, the DFSP performs some validation such as: +1. Determine that the `payer` identifier exists, and is one that was issued by this DFSP to the PISP specified in the `FSPIOP-Source`. +2. Confirms that the `Consent` that is identified by the `payer` identifier exists, and is valid. +3. Confirm that the User's account is active and holds enough funds to complete the transaction. +4. Any other validation that the DFSP wishes to do. + +Should this validation succeed, the DFSP will generate a unique `transactionId` for the request, and call **PUT /thirdpartyRequests/transactions/**_{ID}_ with this `transactionId` and a `transactionRequestState` of `RECEIVED`. + +This call informs the PISP that the Thirdparty Transaction Request was accepted, and informs them of the final `transactionId` to watch for at a later date. + +If the above validation fail, the DFSP should send a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** call to the PISP, +with an error message communicating the failure to the PISP. See [Error Codes](./data-models.md#errorcodes) for more information. + +### 3.2.2 Thirdparty Authorization Request + +The Payer DFSP (that is, the institution sending funds at the request of the PISP) may then issue a quotation request (**POST /quotes**) to the Payee DFSP (that is, the institution receiving the funds). Upon receiving the **PUT /quotes/**_{ID}_ callback from the Payee DFSP, the Payer DFSP needs to confirm the details of the transaction with the PISP. + +They use the API call **POST /thirdpartyRequests/authorizations**. The request body is populated with the following fields: + +- `transactionRequestId` - the original id of the **POST /thirdpartyRequests/transactions**. Used by the PISP to correlate an Authorization Request to a Thirdparty Transaction Request +- `authorizationRequestId` - a random UUID generated by the DFSP to identify this Thirdparty Authorization Request +- `challenge` - the challenge is a `BinaryString` which will be signed by the private key on the User's device. While the challenge +could be a random string, we recommend that it be derived from something _meaningful_ to the actors involved in the transaction, +that can't be predicted ahead of time by the PISP. See [Section 4.1](#DerivingtheChallenge) for an example of how the challenge +could be derived. +- `transactionType` the `transactionType` field from the original **POST /thirdpartyRequests/transactions** request + + +![1-2-2-authorization](./assets/diagrams/transfer/1-2-2-authorization.svg) + + +### 3.2.3 Signed Authorization + +Upon receiving the **POST /thirdpartyRequests/authorizations** request from the Payer DFSP, the PISP presents the terms of the proposed +transaction to the user, and asks them if they want to proceed. + +The results of the authorization request are returned to the DFSP via the **PUT /thirdpartyRequests/authorizations/**_{ID}_, where +the *{ID}* is the `authorizationRequestId`. + + +If the user rejects the transaction, the following is the payload sent in **PUT /thirdpartyRequests/authorizations/**_{ID}_: + +```json +{ + "responseType": "REJECTED" +} +``` + +![1-2-3-rejected-authorization](./assets/diagrams/transfer/1-2-3-rejected-authorization.svg) + + +Should the user accept the transaction, the payload will depend on the `credentialType` of the `Consent.credential`: + +1. If `FIDO`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. + The `signedPayload.fidoSignedPayload` is the `FIDOPublicKeyCredentialAssertion` returned from the FIDO Assertion process. See [3.2.3.1 Signing the Challenge FIDO](#SigningTheChallengeFIDO) + +2. If `GENERIC`, the private key created during the [credential registration process](../linking/README.md#162-registering-the-credential) is + used to sign the challenge. See [3.2.3.2 Signing the Challenge with a GENERIC Credential](#SigningTheChallengeGeneric) + +#### 3.2.3.1 Signing the Challenge FIDO + +For a `FIDO` `credentialType`, the PISP asks the user to complete the [FIDO Assertion](https://webauthn.guide/#authentication) flow to sign the challenge. The `signedPayload.value` is the [`PublicKeyCredential`](https://w3c.github.io/webauthn/#publickeycredential) returned from the FIDO Assertion process, where the `ArrayBuffer`s are parsed as base64 encoded utf-8 strings. As a `PublicKeyCredential` is the response of both the FIDO Attestation and Assertion, we define the following interface: `FIDOPublicKeyCredentialAssertion`: + + +```json +FIDOPublicKeyCredentialAssertion { + "id": "string", + "rawId": "string - base64 encoded utf-8", + "response": { + "authenticatorData": "string - base64 encoded utf-8", + "clientDataJSON": "string - base64 encoded utf-8", + "signature": "string - base64 encoded utf-8", + "userHandle": "string - base64 encoded utf-8", + }, + "type": "public-key" +} +``` + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "FIDO", + "fidoSignedPayload": FIDOPublicKeyCredentialAssertion + } +} +``` + +![1-2-3-signed-authorization-fido](./assets/diagrams/transfer/1-2-3-signed-authorization-fido.svg) + + +#### 3.2.3.2 Signing the Challenge with a GENERIC Credential + +For a `GENERIC` credential, the PISP will perform the following steps: + + +1. Given the inputs: + - `challenge` (`authorizationRequest.challenge`) as a base64 encoded utf-8 string + - `privatekey` (stored by the PISP when creating the credential), as a base64 encoded utf-8 string + - SHA256() is a one way hash function, as defined in [RFC6234](https://datatracker.ietf.org/doc/html/rfc6234) + - sign(data, key) is a signature function that takes some data and a private key to produce a signature +2. _Let `challengeHash` be the result of applying the SHA256() function over the `challenge`_ +3. _Let `signature` be the result of applying the sign() function to the `challengeHash` and `privateKey`_ + +The response from the PISP to the DFSP then uses this _signature_ as the `signedPayload.genericSignedPayload` field: + + +The final payload of the **PUT /thirdpartyRequests/authorizations/**_{ID}_ is then: + +```json +{ + "responseType": "ACCEPTED", + "signedPayload": { + "signedPayloadType": "GENERIC", + "genericSignedPayload": "utf-8 base64 encoded signature" + } +} +``` + +![1-2-3-signed-authorization-generic](./assets/diagrams/transfer/1-2-3-signed-authorization-generic.svg) + + +### 3.2.4 Validate Authorization + +> __Note:__ If the DFSP uses a self-hosted authorization service, this step can be skipped. + +The DFSP now needs to check that challenge has been signed correctly, and by the private key that corresponds to the +public key that is attached to the `Consent` object. + +The DFSP uses the API call **POST /thirdpartyRequests/verifications**, the body of which is comprised of: + +- `verificationRequestId` - A UUID created by the DFSP to identify this verification request. +- `challenge` - The same challenge that was sent to the PISP in [3.2.2 Thirdparty Authorization Request](#ThirdpartyAuthorizationRequest) +- `consentId` - The `consentId` of the Consent resource that contains the credential public key with which to verify this transaction. +- `signedPayloadType` - The type of the SignedPayload, depending on the type of credential registered by the PISP +- `fidoValue` or `genericValue` - The corresponding field from the **PUT /thirdpartyRequests/authorizations** request body from the PISP. +The DFSP must lookup the `consentId` based on the `payer` details of the `ThirdpartyTransactionRequest`. + +![1-2-4-verify-authorization](./assets/diagrams/transfer/1-2-4-verify-authorization.svg) + +## 3.3 Transfer + +Upon validating the signed challenge, the DFSP can go ahead and initiate a standard Mojaloop Transaction using the FSPIOP API. + +After receiving the **PUT /transfers/**_{ID}_ call from the switch, the DFSP looks up the ThirdpartyTransactionRequestId for the given transfer, +and sends a **PATCH /thirdpartyRequests/transactions/**_{ID}_ call to the PISP. + +Upon receiving this callback, the PISP knows that the transfer has completed successfully, and can inform their user. + +![1-3-transfer](./assets/diagrams/transfer/1-3-transfer.svg) + + +# 4. Request TransactionRequest Status + +A PISP can issue a **GET /thirdpartyRequests/transactions/**_{ID}_ to find the status of a transaction request. + +![PISPTransferSimpleAPI](./assets/diagrams/transfer/get_transaction_request.svg) + +1. PISP issues a **GET /thirdpartyRequests/transactions/**_{ID}_ +1. Switch validates request and responds with `202 Accepted` +1. Switch looks up the endpoint for `dfspa` for forwards to DFSP A +1. DFSPA validates the request and responds with `202 Accepted` +1. DFSP looks up the transaction request based on its `transactionRequestId` + - If it can't be found, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP Ensures that the `FSPIOP-Source` header matches that of the originator of the **POST /thirdpartyRequests/transactions** + - If it does not match, it calls **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** to the Switch, with a relevant error message + +1. DFSP calls **PUT /thirdpartyRequests/transactions/**_{ID}_ with the following request body: + ``` + { + transactionRequestState: TransactionRequestState + } + ``` + + Where `transactionId` is the DFSP-generated id of the transaction, and `TransactionRequestState` is `RECEIVED`, `PENDING`, `ACCEPTED`, `REJECTED`, as defined in [7.5.10 TransactionRequestState](https://github.com/mojaloop/mojaloop-specification/blob/master/fspiop-api/documents/v1.1-document-set/API%20Definition%20v1.1.md#7510-transactionrequeststate) of the API Definition + + +1. Switch validates request and responds with `200 OK` +1. Switch looks up the endpoint for `pispa` for forwards to PISP +1. PISP validates the request and responds with `200 OK` + +# 5. Error Conditions + +After the PISP initiates the Thirdparty Transaction Request with **POST /thirdpartyRequests/transactions**, the DFSP must send either a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** or **PATCH /thirdpartyRequests/transactions/**_{ID}_ callback to inform the PISP of a final status to the Thirdparty Transaction Request. + +- **PATCH /thirdpartyRequests/transactions/**_{ID}_ is used to inform the PISP of the final status of the Thirdparty Transaction Request. This could be either a Thirdparty Transaction Request that was rejected by the user, or a Thirdparty Transaction Request that was approved and resulted in a successful transfer of funds. +- **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** is used to inform the PISP of a failed Thirdparty Transaction Request. +- If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly + + +## 5.1 Unsuccessful Payee Lookup + +When the PISP performs a Payee lookup (**GET /parties/**_{Type}/{ID}_), they may receive the callback **PUT /parties/**_{Type}/{ID}_**/error**. + +See [6.3.4 Parties Error Callbacks](https://docs.mojaloop.io/mojaloop-specification/documents/API%20Definition%20v1.0.html#634-error-callbacks) of the FSPIOP API Definition for details on how to interpret use this error callback. + +In this case, the PISP may wish to display an error message to their user informing them to try a different identifier, or try again at a later stage. +## 5.2 Bad Thirdparty Transaction Request + +When the DFSP receives the **POST /thirdpartyRequests/transactions** request from the PISP, the following processing or validation errors may occur: +1. The `payer.partyIdType` or `payer.partyIdentifier` is not valid, or not linked with a valid **Consent** that the DFSP knows about +2. The user's account identified by `payer.partyIdentifier` doesn't have enough funds to complete the transaction +3. The currency specified by `amount.currency` is not a currency that the user's account transacts in +4. `payee.partyIdInfo.fspId` is not set - it's an optional property, but payee fspId will be required to properly address quote request +5. Any other checks or verifications of the transaction request on the DFSP's side fail + +In this case, the DFSP must inform the PISP of the failure by sending a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-2-1-bad-tx-request](./assets/diagrams/transfer/3-2-1-bad-tx-request.svg) + +The PISP can then inform their user of the failure, and can ask them to restart the Thirdparty Transaction request if desired. + + +## 5.3 Downstream FSPIOP-API Failure + +The DFSP may not want to (or may not be able to) expose details about downstream failures in the FSPIOP API to PISPs. + +For example, before issuing a **POST /thirdpartyRequests/authorizations** to the PISP, if the **POST /quotes** call with the Payee FSP fails, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + +![3-3-1-bad-quote-request](./assets/diagrams/transfer/3-3-1-bad-quote-request.svg) + +Another example is where the **POST /transfers** request fails: + +![3-3-2-bad-transfer-request](./assets/diagrams/transfer/3-3-2-bad-transfer-request.svg) + + +## 5.4 Invalid Signed Challenge + +After receiving a **POST /thirdpartyRequests/authorizations** call from the DFSP, the PISP asks the user to sign the `challenge` using the credential that was registered during the account linking flow. + +The signed challenge is returned to the DFSP with the call **PUT /thirdpartyRequest/authorizations/**_{ID}_. + +The DFSP either: +1. Performs validation of the signed challenge itself +2. Queries the Auth-Service with the **thirdpartyRequests/verifications** resource to check the validity of the signed challenge against the publicKey registered for the Consent. + +Should the signed challenge be invalid, the DFSP sends a **PUT /thirdpartyRequests/transactions/**_{ID}_**/error** callback to the PISP. + + +### Case 1: DFSP self-verifies the signed challenge + +![3-4-1-bad-signed-challenge-self-hosted](./assets/diagrams/transfer/3-4-1-bad-signed-challenge-self-hosted.svg) + + +### Case 2: DFSP uses the hub-hosted Auth-Service to check the validity of the signed challenge against the registered credential. + +![3-4-2-bad-signed-challenge-auth-service](./assets/diagrams/transfer/3-4-2-bad-signed-challenge-auth-service.svg) + +## 5.5 Thirdparty Transaction Request Timeout + +If a PISP doesn't receive either of the above callbacks within the `expiration` DateTime specified in the **POST /thirdpartyRequests/transactions**, it can assume the Thirdparty Transaction Request failed, and inform their user accordingly. + + +![3-6-tpr-timeout](./assets/diagrams/transfer/3-6-tpr-timeout.svg) + +# 6. Appendix + +## 6.1 Deriving the Challenge + +1. _Let `quote` be the value of the response body from the **PUT /quotes/**_{ID}_ call_ +2. _Let the function `CJSON()` be the implementation of a Canonical JSON to string, as specified in [RFC-8785 - Canonical JSON format](https://tools.ietf.org/html/rfc8785)_ +3. _Let the function `SHA256()` be the implementation of a SHA-256 one way hash function, as specified in [RFC-6234](https://tools.ietf.org/html/rfc6234)_ +4. The DFSP must generate the value `jsonString` from the output of `CJSON(quote)` +5. The `challenge` is the value of `SHA256(jsonString)` \ No newline at end of file diff --git a/vuepress/docs/api/thirdparty/transaction-patterns.md b/vuepress/docs/api/thirdparty/transaction-patterns.md new file mode 100644 index 00000000..5110f83e --- /dev/null +++ b/vuepress/docs/api/thirdparty/transaction-patterns.md @@ -0,0 +1,6 @@ +## Transaction Patterns + +The interactions and examples of how a DFSP and PISP will interact with the Third Party API can be found in the following Transaction Patterns Documents: + +1. [Linking](./transaction-patterns-linking.md) describes how an account link and credential can be established between a DFSP and a PISP +2. [Transfer](./transaction-patterns-transfer.md) describes how a PISP can initate a payment from a DFSP's account using the account link \ No newline at end of file