Callback API

Callback 호출

POST VEGA_VERIFICATION_CALLBACK_API_PATH

Enclave 환경 변수:

VEGA_VERIFICATION_CALLBACK_API_PATH 변수에, Callback API 엔드포인트를 명시합니다.

비동기 방식으로 API가 호출되었을 경우 사용되는 Callback API입니다.

비동기로 동작하는 API는 아래와 같습니다.

  • 사용자 검증 요청 API

  • 트랜잭션 결과 리포트 API

  • 에러 상황 리포트 API

  • Chainalysis KYT 기능을 이용한 위험 평가 API

  • Refinitiv WCO 기능을 이용한 위험 평가 API

Callback API는 enclave에서 호출하는 API로 다음과 같은 경우에 호출됩니다.

  • 이전에 요청했던 Verification에 대한 결괏값이 도착했을 경우 (callbackType : VERIFICATION_RESULT)

  • 송신 VASP에서 특정 verification에 대응되는 txHash 또는 txID의 report가 도착했을 경우 (callbackType : TX_REPORT)

  • 송신 VASP에서 특정 verification에 대응되는 에러 상황 report가 도착했을 경우 (callbackType : ERROR_REPORT)

  • 기존에 등록한 Chainalysis KYT 요청에 대한 위험 평가 결과를 수신했을 경우 (callbackType : CHAINALYSIS_KYT_RESULT)

  • 기존에 등록한 Refinitiv WCO 요청에 대한 위험 평가 결과를 수신했을 경우 (callbackType : REFINITIV_WCO_RESULT)

응답 시간:

이 Callback API는 1초 이내에 응답해야 합니다.

구현 정책

  • 200 OK 코드 외 다른 HTTP response status code를 반환해서는 안 됩니다.

  • API에 대한 response는 가급적 빨리 반환해야 합니다. 따라서 callback API 내부적으로 시간이 오래 걸리는 작업은 비동기로 처리해야 합니다.

  • 멱등성(Idempotent)을 보장하도록 구현해야 합니다.

    • enclave 내부에서 데이터 유실을 방지하기 위해 똑같은 데이터로 callback이 여러 번 호출될 수 있습니다.

    • 따라서 중복 데이터를 수신했을 경우에도 이전과 똑같은 동작을 하도록 보장해야 합니다. (예를 들어 이미 받은 데이터는 무시한다든지)

Request Header

Field Name
Description

Authorization

Bearer <VEGA_VERIFICATION_AUTHORIZATION_TOKEN>

Request Body

Request Body Example for VERIFICATION_RESULT callbackType
{
  "callbackType": "VERIFICATION_RESULT",
  "data": {
    "verificationUuid": "64ab871b-14a3-47df-9b80-368e29fe8180",
    "verificationResult": "DENIED",
    "reason": "UNKNOWN-ADDRESS",
    "ivms101": {
      "originator": {
        "originatorPersons": [
          {
            "naturalPerson": {
              "name": {
                "nameIdentifier": [
                  {
                    "primaryIdentifier": "James",
                    "secondaryIdentifier": "Din",
                    "nameIdentifierType": "LEGL"
                  }
                ]
              }
            }
          }
        ],
        "accountNumber": ["0x5811001506550d8356a215be229c15b6ef371a9a"]
      },
      "beneficiary": {
        "beneficiaryPersons": [
          {
            "naturalPerson": {
              "name": {
                "nameIdentifier": [
                  {
                    "primaryIdentifier": "Taylor",
                    "secondaryIdentifier": "Robbins",
                    "nameIdentifierType": "LEGL"
                  }
                ]
              }
            }
          }
        ],
        "accountNumber": ["0xb0bFf9721871e22653358956cf59a5FdBF3D752F"]
      },
      "originatingVASP": {
        "legalPerson": {
          "name": {
            "nameIdentifier": [
              {
                "legalPersonName": "Lambda256",
                "legalPersonNameIdentifierType": "LEGL"
              }
            ]
          },
          "geographicAddress": [
            {
              "addressType": "GEOG",
              "postcode": "123123c",
              "townName": "Yeoksam-dong",
              "addressLine": ["sechogu street", "100-100"],
              "country": "KR"
            }
          ],
          "nationalIdentification": {
            "nationalIdentifier": "KR0001",
            "nationalIdentifierType": "RAID",
            "registrationAuthority": "RA000151"
          }
        }
      },
      "beneficiaryVASP": {
        "legalPerson": {
          "name": {
            "nameIdentifier": [
              {
                "legalPersonName": "Lambda256 Exchange",
                "legalPersonNameIdentifierType": "LEGL"
              }
            ]
          },
          "geographicAddress": [
            {
              "addressType": "GEOG",
              "postcode": "234234",
              "townName": "Yeoksam-dong",
              "addressLine": ["sechogu street", "100-100"],
              "country": "KR"
            }
          ],
          "nationalIdentification": {
            "nationalIdentifier": "123456",
            "nationalIdentifierType": "RAID",
            "registrationAuthority": "RA000677"
          }
        }
      }
    }
  }
}
Request Body Example for TX_REPORT callbackType
{
  "callbackType": "TX_REPORT",
  "data": {
    "verificationUuid": "64ab871b-14a3-47df-9b80-368e29fe8181",
    "txHash": "8a54d58ca4100112a5430818776d74898f2232770bae03046862575cb851a042",
    "vout": "2"
  }
}
Request Body Example for ERROR_REPORT callbackType
{
  "callbackType": "ERROR_REPORT",
  "data": {
    "verificationUuid": "64ab871b-14a3-47df-9b80-368e29fe8182",
    "result": "ERROR",
    "reason": "BLACKLISTED",
    "message": "Originator is included in the blacklist."
  }
}
Request Body Example for CHAINALYSIS_KYT_RESULT callbackType
{
  "callbackType": "CHAINALYSIS_KYT_RESULT",
  "data": {
    "verificationUuid": "69a310e6-810f-4a31-83d1-bcdafccf5304",
    "riskAssessment": {
      "chainalysisKYT": {
        "counterpartyVaspId": "15952089931162059995",
        "apiType": "ATTEMPT",
        "userId": "15952089931162059995",
        "direction": "OUTGOING",
        "network": "ETHEREUM",
        "asset": "ETH",
        "amount": "1",
        "usdPrice": "1820.17",
        "outputAddress": "bb3fd383d1c5540e52ef0a7bcb9433375793aeaf",
        "timestamp": "2023-05-18T12:39:44.000Z",
        "externalId": "79382ac9-c7be-3fab-ad56-8c61c654e2fc",
        "status": "PROCESSED",
        "alertCount": 1,
        "createdAt": "2023-05-18T12:39:46.000Z",
        "assessedAt": "2023-05-18T12:39:45.263Z"
      },
      "chainalysisKYTAlerts": [
        {
          "counterpartyVaspId": "15952089931162059995",
          "externalId": "79382ac9-c7be-3fab-ad56-8c61c654e2fc",
          "direction": "OUTGOING",
          "alertId": "118b8cc8-f579-11ed-b86d-a3210c6ca9b8",
          "alertLevel": "MEDIUM",
          "entityCategory": "high risk exchange",
          "serviceName": "HIGH RISK EXCHANGE: SimpleSwap.io bb3fd383d1c5540e52ef0a7bcb9433375793aeaf",
          "exposureType": "DIRECT",
          "alertAmount": "1820.17",
          "createdAt": "2023-05-18T12:39:52.461Z"
        }
      ]
    }
  }
}
Request Body Example for REFINITIV_WCO_RESULT callbackType
{
  "callbackType": "REFINITIV_WCO_RESULT",
  "data": {
    "verificationUuid": "69a310e6-810f-4a31-83d1-bcdafccf5304",
    "riskAssessment": {
      "refinitivWorldCheckOne": {
        "counterpartyVaspId": "15952089931162058999",
        "direction": "INCOMING",
        "caseSystemId": "5jb7r2c9xjfk1hoc95gfayv6m",
        "status": "PROCESSED",
        "matchStrength": "EXACT",
        "aggregatedSummaryResult": "{\"caseId\":\"69a310e6-810f-4a31-83d1-bcdafccf5304-INCOMING-1684413585757\", ... }}}",
        "createdAt": "2023-05-18T12:39:48.000Z",
        "assessedAt": "2023-05-18T12:39:57.834Z"
      }
    }
  }
}
Field Name
Data Type
Required
Description

callbackType

string

true

Callback API가 어떠한 상황에서 호출되었는지 구분하는 값. (하단 설명 참조)

data

object

true

callbackType에 따라 data 형식이 달라집니다. (위 샘플 코드 참조)

  • callbackType 필드에는 다음과 같은 값이 들어갈 수 있습니다.

    • VERIFICATION_RESULT: 이전에 호출했던 사용자 검증 요청 API에 대한 결과가 도착했을 때 호출

    • TX_REPORT: Originating VASP로부터 트랜잭션 결과 리포트가 도착했을 때 호출

    • ERROR_REPORT: Beneficiary VASP로부터 에러 상황 리포트가 도착했을 때 호출

    • CHAINALYSIS_KYT_RESULT: Chainalysis KYT API를 이용하여 위험 평가를 수행한 결과가 도출되었을 때 호출

    • REFINITIV_WCO_RESULT: Refinitiv WCO API를 이용하여 위험 평가를 수행한 결과가 도출되었을 때 호출

  • data.reason 필드에는 다음과 같은 값이 들어갈 수 있습니다.

    • 단, 사용자 검증 요청에 대한 결과 data.result 필드의 값이 DENIED 일 때에만 유효합니다.

    • data.message 필드에는, 아래 표에 설명된 값을 string으로 전달합니다. (하단 표 내용 참조)

    reason

    (string)

    result

    (string)

    message

    (string)

    Description

    UNKNOWN-SYMBOL

    DENIED

    해당 VASP에서 취급하지 않는다고 판명된 심벌 이름

    거래소에서 취급하지 않는 심벌일 경우 (VASP가 취급하지 않는 자산일 경우)

    UNKNOWN-NETWORK

    DENIED

    해당 VASP에서 취급하지 않는다고 판명된 네트워크 이름

    거래소에서 취급하지 않는 네트워크이거나 네트워크 정보가 불충분한 경우 (심벌은 동일하지만 네트워크가 맞지 않는 경우)

    UNKNOWN-ADDRESS

    DENIED

    해당 VASP 소유의 주소가 아니라고 판명된 지갑 주소

    가상 자산 주소가 해당 VASP의 주소가 아닌 경우

    LACK-OF-INFORMATION

    DENIED

    부족한 개인 정보 필드 코드 목록 (쉼표로 구분)

    상대방 사용자의 정보가 검증을 수행하기에 부족한 경우

    UNAVAILABLE-INFORMATION

    DENIED

    넘겨줄 수 없는 개인 정보 필드 코드 목록 (쉼표로 구분)

    상대방이 요청한 개인 정보가 없거나 넘겨줄 수 없는 경우

    BLACKLISTED

    DENIED

    -

    상대방 사용자에 대한 sanction screening 결과 문제가 있는 경우

    UNVERIFIED-KYC

    DENIED

    -

    자신의 VASP의 해당 사용자가 KYC 인증이 되어 있지 않은 경우

    MISMATCHED-NAME

    DENIED

    -

    수신자의 이름이 송신 VASP에서 보내준 이름과 일치하지 않는 경우

    NOT-ALLOWED

    DENIED

    거부 사유

    수신 VASP에서 어떤 이유로든 해당 사용자 검증 요청을 거부한 경우

    UNDEFINED-ERROR

    DENIED

    에러 내용

    그 밖에, 따로 정의되어 있지 않은 에러가 발생한 경우

    BENEFICIARY-ACCOUNT-NOT-MATCHED

    ERROR

    -

    송신자가 입력한 수신자 주소가 수신 VASP에 의해 변경되어 반환되었을 경우

    REQUEST-TIMEOUT

    ERROR

    -

    수신 VASP에서 사용자 검증 VASP API 호출이 시간 초과로 실패했을 경우

Response Body

Response Body Examples
  • 200 OK

{
  "result": true
}
Field Name
Data Type
Required
Example
Description

result

boolean

true

true

결괏값. (에러는 반환하지 않습니다.)

Last updated