Last updated 1 week ago

KYC integration guide

Gathering docs

Your AppCustomerRebillypasswordless loginlogin tokenexchange token with limited ACLA customer-scoped storefront token (JWT)Click to "KYC"redirect with JWT to "KYC document gatherer"File (identity document)File token referenceAnalyze document by reference tokenDocument rejected, correction suggestion (...)All goodalt[is rejected][is good]RedirectYour AppCustomerRebilly
  1. Look up a customer (and create one if not found).
  2. Generate a passwordless login token. We recommend using passwordless for this KYC document gatherer experience (which means you have already authenticated your customer in some other way -- such as they have logged into your website).
  3. Exchange the login token for a storefront API token (JWT). We would recommend to limit the access for the customer to only the required API operations for the KYC document gatherer.

    {
      "type": "customer",
      "token": "replace_with_login_token",
      "customerId": "replace_with_customer_id",
      "acl": [
        {
          "scope": {
            "organizationId": [
              "replace_with_organization_id"
            ]
          },
          "permissions": [
            "PostFile",
            "StorefrontGetWebsite",
            "StorefrontGetAccount",
            "StorefrontGetKycDocumentCollection",
            "StorefrontGetKycDocument",
            "StorefrontPostKycDocument"
          ]
        }
      ],
      "customClaims": {
          "documents": ["identity-proof", "address-proof"],
          "redirectUrl": "https://mywebsite.com",
      },
    }
  4. Form the KYC document gatherer link. It is composed of parts:
Part Description
server name Our sandbox app server is demo.comply.services. Our live app server is verification.comply.services. If you made a custom app, it will live at a different server name.
token This token is the storefront JWT. First, you need to Generate a login token. The KYC document gatherer experience is geared for a passwordless token when the customer is already authenticated in your system.
Specify the accepted document types by setting the documents array. Valid types are identity-proof and address-proof. To collect multiple identities, supply multiple identity-proof values in the array. Example: ["identity-proof", "address-proof"].
Set the redirect URL by setting the redirectURL. At the end of either 3 bad attempts or a success, the customer will be redirected to the redirectUrl.
Determine how long the token is valid for by setting the expiredTime (for example, set it 1 hour in the future for it to be valid for 1 hour, 1 day in the future for it to be valid for 1 day). The recommendation is to keep it shorter when linking from a logged-in user-interface, and longer when linking from an email. Then, exchange it for a customer-scoped JWT storefront token.
https://{server name}/?token={storefront JWT token}

Here is a real fully-formed URL (which has already expired):

https://demo.comply.services/?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJMNndIOFZhVmJHSnozR1d3am52TVo4ckxEU1Z1dHFmRyIsImV4cCI6MTU5MjM1NTYyNSwidXNlciI6eyJpZCI6IjMxYTdjYjM2LWRlNDMtNGMwOS05N2JlLWY4OGQwZDU3NDhhNiIsIm5hbWUiOiJSZWJpbGx5IFN1cHBvcnQiLCJlbWFpbCI6InN1cHBvcnRAcmViaWxseS5jb20iLCJjcmVhdGVkVGltZSI6IjIwMTYtMDMtMjNUMTY6NDg6MTQrMDA6MDAifSwidXNlckhhc2giOiJlZWVjZmEyMmRhMjRkYmExMGJkNTE4Y2EwZTM4NTMzMjA3NTRmYmI0NTJkNGNjYTM1NjkxNGJmNDZkNTc1ZWEzIiwiY3VzdG9tZXIiOnsibmFtZSI6Ik1hdHRoZXcgU2FuZm9yZCIsImNyZWF0ZWRUaW1lIjoiMjAyMC0wNi0xNlQyMjoxOTo1MCswMDowMCIsImlkIjoiYzg4MGU0MTItOGNlYi00YTI5LThlNTktMTY1MjI0MTVjNmY5In0sImFjbCI6W3sic2NvcGUiOnsib3JnYW5pemF0aW9uSWQiOlsiNjBmNjA1YTUtMzJjZC00ODg1LThiNDQtNDk4YzQxY2RlYjk1Il19LCJwZXJtaXNzaW9ucyI6WyJQb3N0RmlsZSIsIlN0b3JlZnJvbnRHZXRLeWNEb2N1bWVudENvbGxlY3Rpb24iLCJTdG9yZWZyb250R2V0S3ljRG9jdW1lbnQiLCJTdG9yZWZyb250UG9zdEt5Y0RvY3VtZW50Il19XX0.eK326R-Lgb8Q2_vw-0nrejOrvVvLaTsPKUQBshhgwWRF7aZRsaClZQ8gLS4q_hnefSKpGmrhScnqT960HZdVRiVjFioSgvb3R_j2pyG8TfGNZNZWMjJsqVtsFj4lxzWfGOs9a8hf0FOEXNGahCKj7Txj356mS0_ZEzQsXEm7A6-cyrnRE816GPQs0ur7WHKpzNydK3KOE8LAJOrQZxRG1ByU8I1PmENLP96ZN6ysKwztdaBCDP8RlvLkAB_-xgYVgEQGh4_lTS5KPClM8V0m5v6RpXzuLxhsclinbd9bW5Oz2wjp_TntKLT-HJ1i4FKHNha3s66AS9LH8JJQ82aNqA

Finally, redirect your customer to the link, or present them with a call to action to start the KYC process.

Webhooks

Use webhooks to stay updated about the status of KYC documents. Subscribe to these events:

  • kyc document was reviewed
  • kyc document was accepted
  • kyc document was rejected

kyc-webhooks-setup

Here is a sample webhook for one of the events. The difference between the events is the eventType is one of:

  • kyc-document-reviewed
  • kyc-document-accepted
  • kyc-document-rejected
{
    "customerId": "01647209-3184-408d-b83d-e168c90fabe6",
    "kycDocumentId": "614beb8f-8c61-4d8a-ae48-d0a6add1aa94",
    "fileId": "81775d96-afa5-43de-aadb-228bdaa4543b",
    "eventType": "kyc-document-reviewed",
    "_embedded": {
        "customer": {
            "id": "01647209-3184-408d-b83d-e168c90fabe6",
            "email": "johndoe@example.com",
            "firstName": "John",
            "lastName": "Doe",
            "createdTime": "2020-04-24T01:35:51+00:00",
            "updatedTime": "2020-04-24T01:35:51+00:00",
            "customFields": {},
            "defaultPaymentInstrument": null,
            "primaryAddress": {
                "country": null,
                "firstName": "John",
                "lastName": "Doe",
                "organization": null,
                "address": null,
                "address2": null,
                "city": null,
                "region": null,
                "postalCode": null,
                "phoneNumbers": [],
                "emails": [],
                "hash": "e80165adcd7198b1ba59d303c3ef186e7983ada5"
            },
            "lifetimeRevenue": {
                "currency": "EUR",
                "amount": 1,
                "amountUsd": 2
            },
            "invoiceCount": 0,
            "averageValue": {
                "currency": "EUR",
                "amount": 1,
                "amountUsd": 2
            },
            "paymentCount": 1,
            "lastPaymentTime": "2020-04-24T01:35:51+00:00",
            "revision": 1,
            "tags": [],
            "websiteId": "",
            "locale": null,
            "_links": [
                {
                    "rel": "self",
                    "href": "https://api.rebilly.com/v2.1/customers/01647209-3184-408d-b83d-e168c90fabe6"
                },
                {
                    "rel": "attachments",
                    "href": "https://api.rebilly.com/v2.1/attachments?filter=relatedType:customer;relatedId:01647209-3184-408d-b83d-e168c90fabe6"
                }
            ]
        },
        "kycDocument": {
            "id": "614beb8f-8c61-4d8a-ae48-d0a6add1aa94",
            "fileId": "81775d96-afa5-43de-aadb-228bdaa4543b",
            "customerId": "01647209-3184-408d-b83d-e168c90fabe6",
            "documentType": "identity-proof",
            "status": "rejected",
            "createdTime": "2020-04-24T01:35:51+00:00",
            "updatedTime": "2020-04-24T01:35:51+00:00",
            "processedTime": "2020-04-24T01:35:51+00:00",
            "reviewTime": "2020-04-24T01:35:51+00:00",
            "reviewerId": "efe87390-0061-4b71-b9ba-f4833e3b4555",
            "reviewerName": "Test User",
            "rejectionReason": {
                "type": "document-unreadable",
                "message": ""
            },
            "documentMatches": {
                "version": "version_X",
                "score": 1,
                "data": {
                    "containsImage": true,
                    "isIdentityDocument": true,
                    "isPublishedOnline": false,
                    "firstName": "First name",
                    "lastName": "Last Name",
                    "dateOfBirth": "2000-01-01T00:00:00+00:00",
                    "expiryDate": "2030-01-01T00:00:00+00:00",
                    "issueDate": "2020-04-24T01:35:51+00:00",
                    "hasMinimalAge": true
                }
            },
            "revision": 1,
            "_links": [
                {
                    "rel": "self",
                    "href": "https://api.rebilly.com/v2.1/kyc-documents/614beb8f-8c61-4d8a-ae48-d0a6add1aa94"
                }
            ]
        }
    },
    "_links": [
        {
            "rel": "customer",
            "href": "https://api.rebilly.com/v2.1/customers/01647209-3184-408d-b83d-e168c90fabe6"
        },
        {
            "rel": "file",
            "href": "https://api.rebilly.com/v2.1/files/81775d96-afa5-43de-aadb-228bdaa4543b"
        },
        {
            "rel": "kycDocument",
            "href": "https://api.rebilly.com/v2.1/kyc-documents/614beb8f-8c61-4d8a-ae48-d0a6add1aa94"
        }
    ]
}