Server and Web Integration Guide

This guide is for developers integrating ZenKey into their Web applications as well as backend services for clients.

1.0 Background

ZenKey is a secure bridge between your users and the apps and services you provide. As the joint undertaking of the four major US wireless carriers — AT&T, Sprint, Verizon, and T-Mobile — ZenKey leverages encryption technologies in a user's mobile phone and mobile network. The platform packages multiple factors of authentication into a streamlined experience for app and website providers, taking advantage of the unique capabilities and insights of the wireless carriers. It then applies those capabilities to provide an easy and secure way to register, login, and perform other types of authorizations within apps and services. The result for Service Providers (SPs) is a better user experience and a more secure link to users.

1.1 OpenID Connect

ZenKey makes integration easy by following the OpenID Connect (OIDC) authentication protocol. OpenID Connect (OIDC) is an authentication protocol based on the OAuth 2.0 specification. It uses JSON Web Tokens (JWTs) obtained using OAuth 2.0 flows. The ZenKey SDK uses OIDC to support developers creating experiences in web and native applications. You can read more about OIDC here.

1.2 Authorization Flow

ZenKey is simple to use — one method to authenticate into all of your apps and websites (when those third parties have enabled ZenKey). These user flows can take place on the user's primary device, which has the ZenKey app installed, or on a secondary device, such as desktops and tablets.

1.2.1 Authorization on a Primary Device

Users establish their mobile device as their primary device by installing the carrier specific ZenKey app on that device. After completing a simple initial setup, users are ready to use ZenKey with third-party applications. Pressing the ZenKey button in a third party app or website from their primary device starts the authentication process.

Note: This primary device is also the device users can use to authenticate requests from other devices, such as desktops and tablets (see Section 1.2.2: Authorization on Secondary Devices).

High-level Architecture on a Primary Device

Primary Device Flow

Step 1: Your app or website makes an authorization code request to the local ZenKey app.

Step 2: The ZenKey app determines the appropriate wireless carrier to perform SIM and user authentication with and returns an authorization code to your Redirect URI (see Section 3.1.1: Redirect User-Agent).

Step 3: Your backend server may make a token request for user info or other resources which the user consented to share with you.

1.2.2 Authorization on Secondary Devices

Users can also use ZenKey to authenticate on devices other than their primary device, such as a tablet or desktop. These secondary devices rely on the user's primary device to complete the authentication process.

Users pressing the ZenKey button on a secondary device will see a visual and numeric code as a part of the secondary device authorization process. This code allows the user to associate that secondary device with their primary device. From there, they are then instructed to open the ZenKey application on their primary device, where they will be able to complete the authentication request.

High-level Architecture on a Secondary Device

Secondary Device Flow

Step 1: The user is taken to a website where they can select the appropriate carrier. This is known as the carrier Discovery UI website, and is where the user chooses the carrier associated with their primary device. If the user is authorizing a secondary device from an app on a tablet, the SDK will use a webview for this step.

Step 2: The user then scans the visual code or enters the numeric code into the ZenKey app on their primary device.

Step 3: Once the user approves the request in the ZenKey app on their primary device, the carrier Discovery UI website gets redirected to perform authorization with a login_hint_token.

Step 4: Your backend server makes an authorization code request to the appropriate carrier, to perform SIM and user authentication, receives the auth code back at your Redirect URI.

Step 5: Your backend server may make a token request for user info or other resources which the user consented to share with you.

1.3 User Data

To create a secure experience, user info is only shared via a web request from your secure backend to the user's carrier backend. By using a backend server to make calls to the user's carrier, and not the client application, the clientId, clientSecret and user ID token are not revealed to your client.

The ZenKey services itself does not accumulate the personal data used for authentication. That data remains secured by the user's wireless carrier. Encrypted user information is only shared with Service Providers upon user consent. Users are able to choose whether to share their data and specifically what data will be shared with each participating Service Provider.

2.0 Getting Started

To get started integrating the ZenKey with your applications, there are a few things you should do:

  • Log in to the Service Provider Portal.

  • Register your application and obtain a valid client_id and client_secret.

  • Consider whether you will need a custom Redirect URI. When a user authorizes your application, the ZenKey SDK will send an authorization code request to the appropriate carrier, then redirect the user back to the app via your Redirect URI. Your Redirect URI may also be used for callbacks to several ZenKey services. When you configure your Redirect URI in the Service Provider Portal, its scheme must resemble one of the following formats:

    • {client_id}://com.xci.provider.sdk
    • https://URL/URI
    • {custom}://
  • Identify which scopes, or user attributes, to capture when a user authorizes your app. During enrollment, users provide the ZenKey SDK with basic personal information (e.g. name, email, address) while other scopes originate from the carrier without user input (e.g. phone number). When users sign into your app with ZenKey, they can then elect to share that data with you. Besides the mandatory .openid scope, all other scopes are optional.

2.1 Integration Options

In order to support all possible backend technology stacks, ZenKey does not provide SDKs for specific languages or frameworks. Instead, this guide describes the HTTP request flow required to integrate with ZenKey.

We strongly recommend that you leverage an OIDC certified relying party library to abstract away the implementation details of OIDC authentication. Find one here

To aid in the implementation, we provide example applications in several popular languages and frameworks:

2.2 Web Demos

To see how ZenKey works on Node, Java, PHP, or Python, following the demos in this section will allow you to observe the authentication flow from start to finish, to learn how to request available scopes, and complete a request to send money after logging in to the demo app.

Step 1: Sign in with ZenKey

Authentication flows for the Node, Java, PHP, and Python apps are nearly identical. As a result, you may visit any of the following demo pages to get an idea as to how your app should function.

From the demo web app you have chosen, then press the “Sign in with ZenKey” button to log in.

ZenKey SDK Web Demo Sign In

Step 2: Discovery UI

The ZenKey button will now load the Discovery UI web page. If the user has not yet trusted the browser, they will be asked to open the ZenKey app, navigate to “Trusted”, then either capture a code with their camera or enter a numeric code manually.

ZenKey SDK Web Demo Discovery UI Code

Step 3: Login Request Sent

Once the user has trusted the browser, the Discovery UI page should display the last four digits of the phone number associated with that ZenKey account. The user will also see the additional option to “Trust a Different ZenKey Account”. Selecting the trusted account will send a login request to the device configured with that phone number.

ZenKey SDK Web Demo Select Account

Step 4: Push Notification Received

From the web browser, the user will now be instructed to check their phone to confirm the login request.

ZenKey SDK Web Demo Check Phone

The device used in Step 3 will now receive a push notification asking whether the user would like to confirm the transaction.

ZenKey SDK Web Demo Confirm Transaction

Next, the Consent screen will appear within the ZenKey app. Here the user will see which scopes the mobile carrier will share and either “Agree” to share the relevant attributes or “Deny” the request.

ZenKey SDK Web Demo Consent Screen

Step 6: Authentication Redirect

Selecting “Agree” from the Consent Screen will return the message “You have successfully authenticated. Redirecting...” and log the user in to the demo web app. The demo app will now return the JSON response including all the user information requested by your scopes and approved by the user. The sub is an identifier that uniquely pairs a single user with a particular client_id. When you receive the sub, you will store this unique ID in your user database for reference. Do not transmit this sub to your client app.

    "sub": "mccmnc-123456789",  
    "name": "Jane Doe",  
    "given_name": "Jane",  
    "family_name": "Doe",  
    "email": "",  
    "phone_number": "+13101234567",  
    "postal_code": "90210-3456"
Step 7: Send Money

Now that the user is logged in, they web app will also provide the option to send money. Choose an amount to send (please note that this has no actual functionality; it simply shows the flow) and specify a Recipient. Clicking the “Continue with ZenKey” button will then initiate the authentication process again, sending a login request via a push notification that asks the user to confirm the transaction.

ZenKey SDK Web Demo Send Money

Step 8: Confirm Transaction

Upon receipt of the push notification, the ZenKey app on the device will prompt the user to “Confirm” whether they want to share the amount of money specified in the previous step, as well as with name of the recipient.

ZenKey SDK Web Demo Confirm Money Phone

Step 9: Success Screen

Selecting “Confirm” from the device will now load a success screen on the web app, whose message specifies the amount of money sent to the recipient (e.g. “Success: $25.00 was sent to John Doe”).

ZenKey SDK Web Demo Success Screen

3.0 Authentication Flow

The web and server implementation supports authorization on both primary and secondary devices.

If you are implementing ZenKey on a website, the authentication flow begins with a carrier Discovery UI. After a user clicks the ZenKey button on your site, they are taken to a web page that contains a visual and numeric code used to link the web request to the ZenKey application on their primary device.

When supporting iOS and Android implementations, the SDK handles carrier Discovery UI. The step is either skipped, because the app is on the user's primary device, or automatically invoked.

3.1 Carrier Discovery UI

Section 3.1 and its subsections are handled by the iOS or Android SDK within your application on a user's primary device.

The Carrier Discovery UI web page presents the user with a visual and numeric code. The user is prompted to open the ZenKey application on their primary device to authorize the request. If the user is on a device with a SIM card installed, they will be prompted to choose their carrier before preceeding in to the ZenKey app of through the visual code flow outlined above.

The first time a user goes through this step on a device, they create a link between the browser and their ZenKey account known as a Trusted Browser. On subsequent requests to authenticate on that browser, the user will skip the visual and numeric code flow. Instead a push notification will be sent to their primary device, allowing for a more seamless approval of the request.

ZenKey handles all of the logic associated with which of these two Carrier Discovery UI experiences the user should be presented.

3.1.1 Redirect User-Agent

The carrier's DISCOVERY_UI endpoint brings the user to ZenKey's carrier discovery UI, where they then see a visual code or select their carrier's logo.
Parameter Description
CLIENT_ID Your ZenKey clientId obtained in the SP Portal.
REDIRECT_URI ZenKey redirects user back to your app using this URL. The URL will contain an authorization code that your app can exchange for a token. The Redirect URI must be registered to your clientId.
STATE An anti-forgery state token. Generate a unique session token and store it. You will need to match this token with the authentication response to verify that the user is making the request, and not a malicious attacker. (Optional.)
SDK_VERSION Method for the SDK to report version. (Optional.)
PROMPT UI will ignore previous cookies so user can reselect carrier. Prompt may be needed if user has ported to a new carrier and their secondary device has failed authentication with old MNO. SP may re-trigger discovery, forcing UI. (Optional.)

3.1.2 Response

The user is now redirected to your REDIRECT_URI, whose URL also contains the parameters LOGIN_HINT_TOKEN, MCCMNC and STATE. For example:<xxx>&mccmnc=<xx>&state=<state>

The LOGIN_HINT_TOKEN will be used in the Authorization Code request (see Section 3.3); the MCCMNC during the OIDC Discovery request (see Section 3.2); and STATE for validating whether its returned value matches the one sent in the request.

Parameter Description
LOGIN_HINT_TOKEN This will only be returned if the request is made by a secondary device, such as a desktop or tablet. Requests that originate on a user's primary device will not return this parameter.
MCCMNC Six digit code that identifies the user's carrier and resides on every SIM card. You will need to store this for subsequent calls.
STATE Validate against the token generated earlier.

3.2 OIDC Discovery

Section 3.2 and its subsections are handled by the iOS or Android SDK within your application on a user's primary device.

Perform OIDC Discovery to fetch the OpenID Configuration Document for the user's carrier. This call will provide information about the carrier's OpenID configuration, including all necessary endpoints and public key location information. Use as the DISCOVERY_URL variable in your implementation.

3.2.1 Request
Parameter Description
CLIENT_ID Obtained in the ZenKey Service Provider Portal.
MCCMNC Six digit code that identifies the user's carrier and SIM card details.
SUB Pairwise identifier that ties a user to an SP CLIENT_ID. (Optional.)
PHONE_NUMBER Only when a valid CLIENT_ID and CLIENT_SECRET are present may the SP request discovery via the phone number.* (Optional.)
IP SP webserver may make a discovery request passing client's IP. (Optional.)

For discovery requests made only with a PHONE_NUMBER, you may use the "proof of possession" signature Header: x-authorization.

3.2.2 Discovery Response

The carrier's discovery response will contain the OpenID Configuration Document. Ensure that you fetch the OpenID Configuration Document on each authentication request, as it differs based on the user's carrier. Below is a snippet of what a carrier might return:

HTTP/1.1 200 OK
Content_type: application/json
Cache-control: max-age=864000

   "scopes_supported":["openid", "profile", "email", "address", "phone", ".."],
   "response_types_supported":["code", "async_token” ],

3.3 Request Authorization Code

Section 3.3 and its subsections are handled by the iOS or Android SDK within your application on a user's primary device.

When you request an authorization code, it will be to the carrier's AUTHORIZATION_ENDPOINT returned in the discovery response. Also included in your auth code request will be the REDIRECT_URI created when you retrieved your CLIENT_ID and CLIENT_SECRET in the ZenKey Service Provider Portal as well as several other parameters listed below. Note that LOGIN_HINT_TOKEN is optional and should only be included when present in the discovery response.

Parameter Description
AUTHORIZATION_URL The carrier's authorization endpoint from the OpenID Configuration Document.
CLIENT_ID Obtained in the ZenKey Service Provider Portal.
LOGIN_HINT_TOKEN The LOGIN_HINT_TOKEN from the carrier Discovery UI response. This optional parameter will only be returned if the request is made by a secondary device, such as a desktop or tablet. Requests that originate on a user's primary device will not return this parameter. Only include LOGIN_HINT_TOKEN if present in the discovery response. Do not include LOGIN_HINT_TOKEN if the parameter is not present in the response.
REDIRECT_URI The URL in your app that ZenKey will redirect the user back to. Will contain an authorization CODE that your app can exchange for a token. Must exactly match the value specified during registration in SP Portal.
STATE Token generated earlier.
SCOPES User attributes like name, email, phone, and address.

3.3.1 Authorization Response

The user-agent will now be redirected to the specified REDIRECT_URI with these URL parameters.

Parameter Description
CODE Used in Token Request.
STATE Validate value against the token generated earlier.
MCCMNC Needed for SP client to inform SP server of carrier.
CORRELATION_ID Tracking ID used for transaction logging. Defined by SP issuing request. SP must use Service Portal to access log entries.
ERROR Standard OpenID Connect error code returned.
ERROR_DESCRIPTION Human-readable ASCII encoded text description of the error. For instance: “User is on a carrier not yet integrated with ZenKey”. For more info, refer to OIDC specs.

3.4 Token Request

Regardless of client (e.g. desktop, mobile app), all token requests should be performed from a secure server so as not to leak client credentials. As a first step, you will need to begin by encoding your CLIENT_ID and CLIENT_SECRET. (Note: For security purposes, please only store your CLIENT_SECRET on your secure backend and allow as few trusted personnel as possible access to it.)


Next, insert the encoded value above into your Authorization header:

    'Authorization': "Basic {encoded_value_here}"

Note: The authorization header will be deprecated once support for JWKs is released.

Now specify the Content-Type as URL-encoded:

    Content-Type: application/x-www-form-urlencoded

Then include the following parameters in the body of your token request:


Note: Make sure this REDIRECT_URI matches the Redirect URI configured for your app.

To see all these components working together, below is the body of a sample request to a carrier's TOKEN_ENDPOINT:

POST /token HTTP/1.1
Authorization Basic Y2xpZW50aWQ6Y2xpZW50c2VjcmV0
Content-Type: application/x-www-form-urlencoded

Parameter Description
TOKEN_URL The carrier's token endpoint from the OpenID Configuration.
GRANT_TYPE An authorization code or refresh token.
CODE The CODE from authorization code response.
REDIRECT_URI ZenKey redirects user back to your app using this URL.
CODE_VERIFIER Cryptographically random key for PKCE. (Optional.)

3.5 Token Response

The token request returns two important JSON Web Tokens: an ID_TOKEN and an ACCESS_TOKEN. The ACCESS_TOKEN provides access to the scopes via the user info endpoint. The ID_TOKEN contains claims about the user, such as their SUB — an identifier that uniquely pairs a single user with a particular CLIENT_ID. When you receive the SUB, you will store this unique ID in your user database for reference. Do not transmit this SUB to your client app.

Sample Token Response:

HTTP/1.1 200 OK
Content-type: application/json
Cache-control: no-cache

    "access_token": "....",
    "token_type": "Bearer",
    "refresh_token": "8xLOxBtZp8",
    "expires_in": 3600,
    "id_token": "..."

The ID Token above will need to be decoded. Once you decode the JWT payload, you will see how it contains claims about the authentication of your end user. For more information about these parameters, please refer to the table directly below this sample.

Sample Decoded ID Token


    "sub": "ccid-client0001",  
    "aud": "ccid-sp00001",
    "nonce": "n-0S6_WzA2Mj",
    "exp": 1311281970,
    "iat": 1311280970,
    "auth_time": 1311280969,
    "acr": "a3",

Below is a list of parameters returned by the carrier's TOKEN_ENDPOINT:

Parameter Description
ACCESS_TOKEN Bearer token used when making requests to carrier's USERINFO_ENDPOINT.
TOKEN_TYPE Set to "Bearer".
EXPIRES_IN Lifetime of current token.
SCOPE List of scopes user has approved for your app.
CORRELATION_ID Same value that was passed to the carrier in the request.
ID_TOKEN JWT containing user profile info and claims about their authentication, such as "iss", "sub", "iat", "aud", "nonce", "acr", etc.

3.6 Request User Info

To request user info, you will now use your access token by issuing a GET request from your backend to the carrier's USERINFO_ENDPOINT. Always make calls from your secure server to allow for safer transit of user info. A successful call will result in the carrier sharing the scopes your user approved during authorization.

    Content-Type: application/json
    Authorization: Bearer {ACCESS_TOKEN}
    x-authorization: {<key_binding>}
Parameter Description
USERINFO_ENDPOINT Extracted from the discovered carrier’s openid-configuration.
ACCESS_TOKEN Bearer token when making requests to the userInfo endpoint.
x-authorization Key binding signature to prove possession of JWT.

3.7 User Info Response

The response will contain JSON with the user information requested by your scopes and approved by the user.

  "sub": "mccmnc-123456789",
  "name": "Jane Doe",
  "given_name": "Jane",
  "family_name": "Doe",
  "email": "",
  "postal_code": "90210-3456",
  "phone_number": "+13101234567",

4.0 Account Migration

Note: Support for account migration is currently unavailable. The following section is for informational purposes only.

When users change carriers, ZenKey provides you with the support you need. This section describes how the migration process works and best practices for when a user ports his/her account from one carrier to another. In order to see how account migration works, let us imagine a user with the following traits:

  • phone=1234567890
  • mccmnc=310010
  • sub= 310010-{carrierid}

Note: The mccmnc variable is a concatenation of Mobile Country Code (MCC) and Mobile Network Code (MNC). This six-digit number resides on every SIM card. The sub variable is a pairwise identifier that ties a particular user to a particular client_id.

With this in mind, imagine:

  1. The user above visits your app associated with client_id=ccid-SP0001.

  2. Your app with client_id=ccid-SP0001 detects the user as SUB=001001-B and stores/federates the user as verify=001001-B.

4.1 Migration Flow

  1. Now the user migrates phone number 1234567890 from Mobile Network Operator #1 (MNO1) to Mobile Network Operator #2 (MNO2), keeping their device but changing SIM and mccmnc.

  2. The user migrates quickly (e.g., within 15 minutes), so when they try to use your app with client_id=ccid-SP0001, you trigger a login prompt with the phone number.

  3. The SDK in your app submits a discovery request with the new mccmnc to retrieve the OpenID configuration for MNO2.

  4. The SDK in your app constructs the authentication URL, opening in the device browser to MNO2's web authentication endpoint.

  5. MNO2 sees the mobile user agent and posts a banner encouraging the user to download the ZenKey app.

  6. The user downloads, installs, and launches the ZenKey application for MNO2 .

  7. MNO2 notices that the user is not yet registered for the new phone number and: a. Asks: “Would you like to register a new ZenKey carrier account?” or “Would you like to PORT your prior ZenKey carrier account from your previous MNO?” b. Upon seeing that the device has a recently migrated phone line, offers a migration option.

  8. The user selects the option to migrate the existing ZenKey carrier account and is redirected in a WebView to MNO1’s authentication endpoint. (Note: port_data is a scope reserved for carriers only. It informs the carrier to render to the user a confirmation for porting the user identity account to a new carrier. Only carriers using ZenKey may access this scope.) Because the MNO1 authentication request contains the port_data scope, MNO1 knows the authentication is for migration.

  9. MNO1 completes the user authentication before returning the user to MNO2: a. MNO1 may require the user to perform multiple recovery methods because EAP-AKA (SIM) authentication will not work for the user. b. MNO1 signs a port token for each Service Provider using the slow rotating key present in the OpenID configuration reference.

  10. The user completes MNO2 account setup steps: a. MNO2 prepopulates the registration page with the previous name, email, address, etc. b. The user chooses a new PIN. c. MNO2 stores port tokens for each of the previous Service Providers used at MNO1.

  11. MNO2 asks if the user wants to port his/her previously-defined consents for each service provider application, and then returns the user to the Service Provider application with an authentication code.

  12. MNO2 returns an access_token and id_token from the token_endpoint. The access_token is the bearer token when making requests to the userinfo_endpoint. The id_token is a JSON Web Token (JWT) that contains claims about the authentication of an end user by an authorization server, such as sub=mncmcc-002002-Z.

  13. But your backend does not recognize this suband so uses the ISS (i.e. discovery endpoint) to access MNO1’s port_token signing key and verify the signature of the port_token. The port_token is always encoded. However once decoded, its contents will contain the new sub:

        "iss": "",
        "sub": "mncmcc-002002-Z",
        "iat": 1516239022,
        "aud": client_id
  1. Your backend updates the user's sub in its database with the new value. For example, mncmcc-001001-B would become mncmcc-002002-Z.

4.2 Migration Best Practices

When you first authenticate a user, the first id_token should contain a single subject claim. Store this as a reference rather than a phone number or email address, since these profile attributes are liable to change. If you receive a new id_token that contains an AKA claim and an unrecognized sub, you should:

  1. Open the AKA port_token.

  2. Verify the port_token issuer is a trusted carrier. (The Service Provider Portal will contain a list of valid iss URLs.)

  3. Use the port_token :iss value to extract the OpenID configuration` of the old MNO.

  4. Use the OpenID configuration to extract the JWKs for the old MNO.

  5. Use the key ID (KID) in the port_token to identify which JWK key to use to verify the token's signature.

  6. If you have recorded a user with the old subject, update the references to the new subject from the new carrier.

Note: Because a user may choose not to port his/her ZenKey account, or to change carriers by getting a new phone number with the new carrier, you should host methods to update the ZenKey references.

5.0 Next Steps

In a database where you store information about your users, you should record the sub as the primary identifier of a ZenKey user because their phone_number and email may change.

Depending on whether the user is registering or signing in, you will want to create or fetch their user record from your data store, respectively. You may also choose to enrich this user record with information received from the User Info response.

Once you have completed the ZenKey authentication flow, return a session using the session management strategy you're already using for your application. Discard the tokens used throughout this flow.

6.0 Sign-In Buttons

You can use these buttons to begin the ZenKey sign in flow. They can be used on the web and other digital platforms. See the Android integration guide and iOS integration guide for information about using SDK buttons.

6.1 Colored and Light Buttons

The color version of the button should be used on white or light backgrounds. The light button variation should be used on dark backgrounds and in dark mode.

Color Light
Normal Normal, colored button Normal, light button
Focused Focused, colored button Focused, light button
Pressed Pressed, colored button Pressed, light button
Disabled Disabled, colored button Disabled, light button

6.2 CTA Variations

You may also use the "Continue" call to action if it is more suitable to your use case.

Color Light
Normal Normal, colored button Normal, light button
Focused Focused, colored button Focused, light button
Pressed Pressed, colored button Pressed, light button
Disabled Disabled, colored button Disabled, light button

6.3 Micro Buttons

Micro buttons should be used when space is limited. Because the button does not contain a call to action, the user interface must make the button's function clear.

Color Light
Normal Normal, colored button Normal, light button
Focused Focused, colored button Focused, light button
Pressed Pressed, colored button Pressed, light button
Disabled Disabled, colored button Disabled, light button

6.4 Button Usage Guidelines

Please use the provided versions of the buttons: avoid creating your own variations. Do not change the button colors or font.

Buttons may be resized as needed, but the ZenKey symbol should always remain left-aligned. The button call to action should be centered between the ZenKey symbol and the right edge. Prioritize the ZenKey sign-in button whenever possible.

The ZenKey buttons use #008522 green as a primary color. White (#FFFFFF) and black (#000000) are used as secondary colors.


For technical questions, contact support.


Copyright © 2020 ZenKey, LLC.

Revision History

Date Published Document Version ZenKey SDK Version Description
5.01.20 0.0.02 1.0.0 Removed Apache Legal information.
1.31.20 0.0.01 1.0.0 First published version.

Last Update: Document Version 0.0.02, May 01, 2020