This documentation serves as a guide to integrate with Civic’s Secure Identity Platform (SIP). The platform provides partners with functionality such as


There are two integration flows:

Civic Hosted option

The general flow is explained using the example of user signup. Code Flow

1. Signup. The user clicks “Signup with Civic” button on your website page. The eventhandler calls a method in the CivicJS library to initiate signup.

2. Launch Popup. A modal is displayed which contains an iframe to house the QR code. A request is made to the Civic server to generate a QR code for your scope request.

3. QR Code. The server checks that the domain for the parent document of the iframe corresponds to the domain white list set in the partner account before serving the code. The QR code bridges the air gap between the browser and the user’s smart phone.

4. Scan. The user scans the QR code using the Civic mobile app and is prompted to authorize or deny the scope request. The prompt highlights the data that is being requested and the requesting party.

5. Grant Request. Upon granting the request, the data is sent to the Civic server.

6. Verify offline. The Civic SIP server verifies the authenticity and integrity of the attestations received from the user’s mobile app. This process proves that the user data was attested to by Civic and that the user is currently in control of the private keys relevant to the data.

7. Verify on the blockchain. The Civic server then verifies that the attestations are still valid on the blockchain and have not been revoked.

8. Encrypt and cache. The data is encrypted and cached on the Civic server. Once this data is cached, a polling request from the iframe will receive a response containing an authorization code wrapped in a JWT token. The CivicJS browser-side library passes the token to the parent document. Your site is then responsible for passing the JWT token to your server.

9. Authorization Code exchange. Use the Civic SIP sdk on your server to communicate with the Civic SIP server and exchange the authorization code (AC) for the requested user data. The SIP server first validates the JWT token, ensuring it was issued by Civic, is being used by the correct application id, and that the expiry time on the token has not lapsed. The enclosed AC is then verified and the encrypted cached data returned.

10. Decrypt. Your server receives the encrypted data where it is decrypted using your application secret key. The result will contain a userId and any data requested (such as email, mobile number etc).

11. Complete user signup. At this point you can store the necessary data and redirect the user to your app’s logged in experience.

For subsequent logins the userId can be used to associate the user with your accounts system.

Getting Started

Follow the steps below to integrate using the Civic Hosted option.

Sign up for a developer account on the Civic Integration Portal and create a test application. From here, you will be able to generate the keys necessary for encryption used in the steps below.

Basic requests necessary for simple account creation and 2FA are available to all partners who have signed up on the integration portal. Extended KYC Beta access requires Civic approval. Learn more and request access here.


<link rel="stylesheet" href="">

<script src=""></script>

Step 1: Include

Include the civic.sip.js script on your page. This exposes a single global object, civic.


  // Step 2: Instantiate instance of civic.sip
  var civicSip = new civic.sip({ appId: 'ABC123' });
  <button id="signupButton" class="civic-button-a medium" type="button">
      <span>Log in with Civic</span>

Step 2: Initialize

Create an instance of civic.sip, passing in your application ID. This identifies your site to Civic servers. You can find your application ID in the Application details section of the integration portal.

Event Handlers

  // Step 3: Start scope request.
  var button = document.querySelector('#signupButton');
  button.addEventListener('click', function () {
    civicSip.signup({ style: 'popup', scopeRequest: civicSip.ScopeRequests.BASIC_SIGNUP });

  // Listen for data
  civicSip.on('auth-code-received', function (event) {
            event: "scoperequest:auth-code-received",
            response: "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiI2Y2EwNTEzMi0wYTJmLTQwZjItYTg2Yi03NTkwYmRjYzBmZmUiLCJpYXQiOjE0OTQyMjUxMTkuMTk4LCJleHAiOjE0OTQyMjUyOTkuMTk4LCJpc3MiOiJjaXZpYy1zaXAtaG9zdGVkLXNlcnZpY2UiLCJhdWQiOiJodHRwczovL3BoNHg1ODA4MTUuZXhlY3V0ZS1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20vZGV2Iiwic3ViIjoiY2l2aWMtc2lwLWhvc3RlZC1zZXJ2aWNlIiwiZGF0YSI6eyJjb2RlVG9rZW4iOiJjY2E3NTE1Ni0wNTY2LTRhNjUtYWZkMi1iOTQzNjc1NDY5NGIifX0.gUGzPPI2Av43t1kVg35diCm4VF9RUCF5d4hfQhcSLFvKC69RamVDYHxPvofyyoTlwZZaX5QI7ATiEMcJOjXRYQ",
            type: "code"

    // encoded JWT Token is sent to the server
    var jwtToken = event.response;

    // Your function to pass JWT token to your server

  civicSip.on('user-cancelled', function (event) {
          event: "scoperequest:user-cancelled"

  civicSip.on('read', function (event) {
          event: "scoperequest:read"

   // Error events.
   civicSip.on('civic-sip-error', function (error) {
      // handle error display if necessary.
      console.log('   Error type = ' + error.type);
      console.log('   Error message = ' + error.message);

Step 3: Event Handlers

The auth-code-received event contains the following fields:

Field Required Description
event Yes event name
type Yes flow type for the response e.g. “code” for authorization code flow
response Yes JWT Token in base64 encoded format containing authorization code

JWT Tokens

The decoded JWT token example below shows the format of the tokens used to transfer data:

  header: {
    typ: 'JWT', alg: 'ES256'
  payload: {
    jti: '45a59d10-6e93-47f6-9185-adacfe28907a',
    iat: 1494204971.361,
    exp: 1494205151.361,   // 3 minute lifespan
    iss: 'civic-sip-hosted-service',
    aud: '/dev/scopeRequest/authCode',  // valid endpoints for this token
    sub: 'civic-sip-hosted-service',
    data: {
      codeToken: '81f2564c-e7c0-4869-be49-a88f5738534f'
  signature: 'xC3CYCFz-p0RWf2CLnnvfb7Fhksu9vSJgHKQIsP4iakp4HI63xoWZZqEiDgcV5S7CULIty_v0fpvJwSs87BgWQ'

Server Integration

Use the Civic SIP server sdk relevant to your server side environment to complete the server integration of your signup, login or general scope request flow.

Server Installation:

Install the module

npm install civic-sip-api


const civicSip = require('civic-sip-api');

// Step 4: Initialize instance passing your appId and secret.
const civicClient = civicSip.newClient({
  appId: 'CO-ABCDEFG1230934545',
  prvKey: PRIVATE_KEY,
  appSecret: APP_SECRET,

Step 4: Initialize

Create an instance of civic.sip, passing in your application ID, private signing key and secret. Your private keys and secret should only be used on the server and never exposed on the client side. They must be stored securely.


// Step 5: Exchange authorization code for user data.
    .then((userData) => {
        // store user data and userId as appropriate
        console.log('userData = ', JSON.stringify(userData, null, 4));
    }).catch((error) => {

Example of data returned for a ScopeRequest of BASIC_SIGNUP

userData =  {
    "data": [
            "label": "",
            "value": "",
            "isValid": true,
            "isOwner": true
            "label": "contact.personal.phoneNumber",
            "value": "+1 5556187380",
            "isValid": true,
            "isOwner": true
    "userId": "c6d5795f8a059ez5ad29a33a60f8b402a172c3e0bbe50fd230ae8e0303609b42"

Step 5: Exchange Authorization Code

Call exchangeCode with the JWT token you received from the browser session to exchange for the requested user data.

User Data

Each item of user data returned has the following fields:

Field Example Description
label Descriptive identifier.
value Item of requested user data.
isValid true Civic SIP service checks whether or not the data is still considered valid on the blockchain.
isOwner true Civic SIP service challenges the user during scope request approval to ensure the user is in control of the private key originally used in the issuance of the data attestation.

Direct Option

This option is not currently available for general use. If this functionality is required, please contact

Scope Requests

Scope Requests detail specific sets of verified data you wished returned from the user. The two currently available scope requests are detailed below. See Event Handlers for documentation on how to implement these requests.

Basic Sign Up

  var button = document.querySelector('#signupButton');
  button.addEventListener('click', function () {
      style: 'popup',
      scopeRequest: civicSip.ScopeRequests.BASIC_SIGNUP


The BASIC_SIGNUP scope request returns the user’s basic account info - email and phone. It is most commonly used for secure login and signup solutions when no additional identity verification is required.

Label Example Value Description The user’s verified email.
contact.personal.phoneNumber +1-555-555-5555 The user’s verified phone number.

Proof Of Identity

  var button = document.querySelector('#signupButton');
  button.addEventListener('click', function () {
      style: 'popup',
      scopeRequest: civicSip.ScopeRequests.PROOF_OF_IDENTITY


The PROOF_OF_IDENTITY scope request returns the full set of verified information for a user’s identity check. Note that attempting this request without prior approval will return an unauthorized error. Request access here.

Label Example Value Description
documents.genericId.type Passport Type of ID document provided for KYC verification.
documents.genericId.number ABC1112223333 ID string (such as Driver’s License or Passport number) for the document provided. John Peter Smith Name given on the ID document
documents.genericId.dateOfBirth 1980-01-30 Data of birth given on the ID document in YYYY-MM-DD format.
documents.genericId.dateOfIssue 2015-06-15 Issued date of the ID document in YYYY-MM-DD format.
documents.genericId.image /9j/4AA[…] Image of the ID document.
documents.genericId.image_md5 81ece061fd53c479f1f7a0cdfb5d3cf1 md5 hash of the image. USA Issuing country of the ID document.
verifications.levels.CIVIC:IAL1 CIVIC:IAL1 Verification standard used to check the document. This field should be ignored pending future functionality.

Browser Support

To ensure the best possible results, the Civic browser experience is designed for modern desktop browsers that automatically update. Browsers without reliable automatic update systems are supported as current version -1.


Partners have access to our test and live environments via environment specific clientID’s and key pairs. ClientID’s and key pairs can be managed in the partner’s dashboard. It is possible to generate multiple ClientID’s. This allows a partner to assign different clientID’s to different subsystems and applications within the organization. This limits the contagion in the event that a private key is compromised, and only that clientID and key pair need to be regenerated.

Our API is served over HTTPS. To ensure data privacy, unencrypted HTTP is not supported. API requests without authentication will also fail.


Civic uses conventional HTTP response codes to indicate the success or failure of an API request. In general, a response code of 2xx indicates the operation was successful. Other error codes indicate either a client error (4xx) or a server error (5xx).

The Civic API uses the following error codes:

Error Code Meaning
400 Bad Request – Check the response ‘message’ field for details.
401 Unauthorized – Authentication failed.
405 Method Not Allowed – You tried to access an invalid method.
429 Too Many Requests – Your request was throttled by our gateway.
500 Internal Server Error – We had a problem with our server. Try again later.
504 Endpoint Request Timed-out Exception.
Select Language