Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Before using the Generating Proof Endpoint, There are three essential items you'll need to use the endpoint:
encryptedUserDataToken : This token contains your encrypted user data
encryptedDvrToken : This token holds your encrypted DVR data
apiToken : This unique identifier authenticates your requests with the zkPass API
For instructions on creating the encryptedUserDataToken and encryptedDvrToken, refer to our section. It provides a step-by-step guide that covers:
: This creates the keys you'll use for signing your data.
: This step adds a digital signature to your data tokens, ensuring their authenticity.
: This encrypts your data tokens, making them unreadable by anyone without the decryption key.
This section explains how to use the zkPass service using any programming language that we don't currently support.
This guide complements your understanding of our API endpoints by delving into key generation, signing, and encryption. These steps are crucial for securing your data tokens when using zkPass.
This pair consists of two keys: a public key and a private key. Think of them like a lock and key combination.
Public Key: This key is freely shared and used to verify the authenticity of your signed data tokens.
Private Key: Keep this key safe! It's used for signing and decrypting your data tokens.
Signing your data tokens adds a digital signature using your private key. This signature acts like a tamper-proof seal, ensuring anyone receiving the token can confirm it hasn't been altered.
Encryption takes your data tokens and scrambles them using your private key. This makes the data unreadable by anyone who doesn't possess the corresponding public key (which you wouldn't share).
HTTP Method
POST
API endpoint (Playground)
https://playground-zkpass.ssi.id/api/1.0/dvr/1.0/proof
Authorization
base64 form of YOUR_API_KEY:YOUR_API_SECRET
Content-Type
Indicates that the content being sent or received is JSON data
user_data_token
string
Mandatory
encrypted user data token in JWE format
dvr_token
string
Mandatory
encrypted dvr token in JWE format
Authorization: Basic [apiToken]
Content-Type: application/json{
"user_data_token": "[encryptedUserDataToken]",
"dvr_token": "[encryptedDvrToken]"
}{
"status": 200,
"proof": "eyJ0e..."
}We are using elliptic curve cryptography (ECC) for our encryption. The key pair should be generated using P-256 curve. Ensure the generated key pair is in PEM format.
The public key should be encoded in SPKI format, and the private key should be encoded in PKCS#8 format.
PEM format
SPKI encoding
PEM format
PKCS#8 encoding
Here's the example of generating key pair in Typescript.
After this section you should have a key pair consisting of :
publicKeyJWKS
privateKey
Make sure you have both them before proceeding to the next section.
Here's the example for publicKeyJWKS and privateKey.
import crypto from "crypto";
interface PublicKeyJWKS {
x: string;
y: string;
kid: string;
}
function generateKeyPair() {
const keypair = crypto.generateKeyPairSync("ec", {
namedCurve: "prime256v1",
publicKeyEncoding: { type: "spki", format: "pem" },
privateKeyEncoding: { type: "pkcs8", format: "pem" },
});
const lines: string[] = keypair.publicKey.trim().split("\n");
const x = lines[1];
const y = lines[2];
const kid = "kid-for-your-key-pair";
const publicKeyJWKS: PublicKeyJWKS = {
x,
y,
kid,
};
const privateKey: string = keypair.privateKey;
console.log({ publicKeyJWKS, privateKey });
...
}{
publicKeyJWKS: {
x: 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELOmrNI4A9ML4iGJXpYlaZiYGVCxB',
y: 'k+evjhOZEbCLj17o/ZdfEv7dUZIRKRoZ1bud5Gq8OCItDlXkTyMrtWrhdA==',
kid: 'q6ZFSOJcTiZWJWkvUshpFw5v20xstZN/T4lt4zpKsUg='
},
privateKey: '-----BEGIN PRIVATE KEY-----\n' +
'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgrSuv5exgvZGmELOL\n' +
'RkT9fhhRxKW3SQASrTVbENIN5cKhRANCAAQs6as0jgD0wviIYleliVpmJgZULEGT\n' +
'56+OE5kRsIuPXuj9l18S/t1RkhEpGhnVu53karw4Ii0OVeRPIyu1auF0\n' +
'-----END PRIVATE KEY-----\n'
}Before you get started with the zkPass API, here's what you'll need:
User Data Token
DVR Token
The zkPass API uses a familiar approach called basic authentication to ensure secure access. Here's what you'll need:
API Key: This unique identifier acts like your username for the API.
API Secret Key: Consider this your password, but much more secure. Keep it confidential!
To access the API, you'll need to provide both your API Key and API Secret Key in every request you make. They should be included in the authorization header of your requests.
No worries! If you haven't received your API credentials, simply fill out our easy-to-use to request them. We'll get you set up in no time.
Our utilities section provides a detailed guide on creating a key pair. This key pair is used for signing and encrypting your user data token (and DVR token, if needed). Here's a quick overview of the steps involved:
This section provides a detailed reference for all zkPass API endpoints
Make sure you have :
userDataToken
dvrToken
Read section for detail info.
zkPass enhances the security of your data during transport by encrypting it before sending it over the network. The are only two entities that can access the data: the holder and zkPass host running in a Trusted Execution Environment (TEE).
First, find the zkPass public key in the .well-known/jwks.json file at this endpoint: The key you're looking for has a kid (Key ID) of "ServiceEncryptionPubK".
After this section you should have :
Encrypted User Data Token (in JWE Format).
Encrypted DVR Token (in JWE Format).
Here's the example
import { importSPKI, EncryptJWT } from "jose";
async encryptData(userDataOrDvrToken: string): Promise<string> {
const keyUrl = 'https://playground-zkpass.ssi.id/.well-known/jwks.json';
const fetchKeys = await fetch(keyUrl);
const keys = await fetchKeys.json();
const encryptionPubKey = keys.find(
(key: { kid: string }) => key.kid === 'ServiceEncryptionPubK'
);
const zkPassPublicKey =
'-----BEGIN PUBLIC KEY-----\n' +
encryptionPubKey.x +
'\n' +
encryptionPubKey.y +
'\n-----END PUBLIC KEY-----';
const importedPublicKey = await importSPKI(zkPassPublicKey, "ES256");
return await new EncryptJWT({ data: userDataOrDvrToken })
.setProtectedHeader({
alg: "ECDH-ES",
enc: "A256GCM",
})
.encrypt(importedPublicKey);
}{
"encryptedUserDatatoken": "eyJ0eXAiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoielJJdWp5aDdmbG84OU5MbHFweEt0VWpmckhabVd1NVIzNGNkTlhnLVMzUSIsInkiOiJwNHN6LXc3U3pGRTBMbGY2R0Z4cUd2YmtuSHpEaENHY2dMSXZvTHpIbTlZIn0sImFsZyI6IkVDREgtRVMifQ..STqfLlyIzO-vlPu-.ju8WoPSCiLBSIUNw9EzSVjINBVx5NzN_XXb4jd8GjQ8d9USaQ0i9yU2M-kXf-eD8PZDYDvQ3hvuIi25MlRlyf_vWQSIrFuReHmZxQGZE1pcg7QXYRip0u4cfUQotvGjTSsBsa_bdXvH7gAInmalzAW_KrI08yXpT-CylitTwhmlm1RdVGWvGsMlu7u6vWWFHpOgHskN50ExfAWVa5_w93euEbxOcGjgegQTGxJocfyglmXIvIlW4XhwG8sj3OotdJbHvoqFMOfjkDf27HlMgG1jvjB-Af4CpIbdp3oP0suc_aDoayYG7butqMqrgk-OPcyIC5ELyDMWErx5WzPc1DY3icRStyzG2yPbs49l2gCcnubrwVbFZu-BqIE5hB6W7A_3Vfd479Heaec_sKzFJUlj9issy4vydy2Lsp_ldaP3J5p1tYvhxDGvoCvolkGHzwfjaNlciJ1BEfwQxyeipxrkXqzQ8oSgY7q5IPe7PtZ7O7JTpwvwbT04opAQiHatnnPbdlsCECSHj1UHuBNEfXcyK7gdzo9OaYOTPcD_Gbd88Yd8DxbKVH3e3M3z7O-ipqhD9vcuw92iOF9e1q23P9MXqjWjylDxSx4xWf9-imEW8aeGDulIQQBJ8OJZv9I7_eUiBTMWxxGgmcHsLSt7Chcv6uk3qj7yoxRqf22XvnxixOw3EtaVchxglqcdsV4dIWN5ynaJb67qUv2vFyig8XvS3x2b8bHzqS0_rNQy8L6ukzK1U0ndSW3QSqi0hcQ_CEwGzKNi445IhJ-NU_a2eGI_PiLhI2M00zpVjIIkc_bGOWHaB-3yCijUS0NjDhET78KWMTmkAEDPS0JVXni3okEd4mXhskbRr6y4OH-ShANti-FE69TO5KZmKZHkuY41xPO8_XNr1sL61z-LOsWb1nVHwfClUBUvFatIy2ElkxpjAhR-FhEiwk_oq6TXwBwLHEpQ8uJ1Es8jMMz0dtZVAo6D6OoutOH5Bo8JDtXX5uJZ7sY-GQgQX1dKLozbShF5IG40uEoGE_dIrd8MHfYZ_rqFct5tobRw299rCUMS3fcLHsJj1fqZgOGlzpy6ruBUNKZPpmNGzZcUiu2zcVheUKhjr69I7LV8h5gkb4LHkx0_AK8Lxl-jgLo-C3xGDIfG0dnZ3zoLDrK0IaueQNmxX-66rlHWhSCV-pSgJpXUFd-zv-IZix_tfV3svEaHyP9tYDg7MHus9mYkyBS6IyJqtEdmsoEYHwohVCS_lL51oIragrVtNLqXDV784zyEKKNB1XwQt5jL-XdOmrsGlJgzp2gUeeEwonEX0-LniBipeuVIAsFgXJ0ThNsLzm61BSLi5wL4xcyzRh9Bws6FRjchxEPkIq8AeQZaTZOddBx1xT4-vcMtnlAAy5ON10bCULCWm-jaAdI6UGSFur106Nr14Jj1dAFIkPFq1EyLFn_2E5D1RDp3siVJ1GCmCdNeVpy3TiHnmhaCXwZ5QkO4yLru4a8s6yWtL9P4Vktcli6tFMJ68RwdJP98YzPbvtnVjlcSei7B2lorhinEGr0JRJDZVhxujvTaYLlE2bFr1UgrAH8Sr9jpViv4Y2Ux2mFKCPdJXaWPsMc1t_s1JCjavdUnskW6afK0OOquHqoMZZoBJgNPq1HXW04Crkl5dM4D6OunA6afvUqxjpzItUlveN-chXInzVv2hX3ZFl8rWyAG3U0fR9_QJJWMzKGmu.P8Ov7hrTkyYla1iTlmXptg",
"encryptedDvrToken": "eyJ0eXAiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiZXBrIjp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiSXQ0YXljSklYUUdFQWtTUjJfU3ZVRWU2QThHaGtscUkxVGxlNmR1MjFVWSIsInkiOiJNSGctcGU2RjhEUDJVbFhMZW1fd1F4NnFIVUdRS0prNzVqel96a3JnOGpjIn0sImFsZyI6IkVDREgtRVMifQ..CiVm0RozjNyk8DhZ.e2iJK7BzHqObLeB1mxO3kJo_iPZIh8H5p3nV3ZN_MtQasX2vg2jeKyGBFgklILwo9d9Sva83ZF0fOla6L9jdAUrQqXBehoWDwTLir3vjLaqITe3bsKmUIdDInmIaZHeoH3RkTn4PqPsBFDj7zFpTwCWeKBDKgZtckJ1N8gU5R-ohAnwZDzsbinGQ03x8w5UeIlmJyZcSL4MeV1NcSVSXryZIi-w_xuK3wr4JGBqSw993tArrxPfF9jENZfqrLczrYHZ08RW_CZBfjp1TxeQGM2ovlw672T-Fu_EA8giqaK4Oqi5u_a_Ixp6bHuGldtf7EeFcoSgoMP5qoK-nIkkW5mJyRqwwO0wTaYVoohfhYliTrlBdO92BW-lK9LqVjAYEG7H1LeKOmP8e2Ze42w_0BeOMlilLE6xyxSVmGZkqnTpehuIgYZmfbO-ps5pWEFXLQ5pba5tCr_jzl3-F9dGDaT3Gpvo8PM1Hn7fAKHgD6_kPaMm1e2MB8gzcfmjwBjg6M3TQ8P1alNFYgsloxCyMhiwMFx3yxKGfoDBAY-vQtaTyWT57INXFjE9DyLSm8pXxbQmA51bSt9Ke1OoTweSR1a_tBX3jMmNnrROPhS0rDQZfiCntytSuiLqIfiBv7jZOW0nH3BoUJ4DFB7j5P6inqdCl5qRRz1fz78Egij9aXuzXpD79bD6i7by8NTAJAVoXOuEPB8VFFjFA0rx3edxB3CWsGZD5lB64iGNo9WH5YdoxHW1ox6a1Vp0oHb1NYhVlxCMiLjs6R8FD7kFw-Dwl5WydUCyjO50_y_fBIAsUvTcfqS_7vCuvp-2d4WdXtBV8pdXyt-T8DCIMYObDp-X6syO7rl40L2i998euEj1cUJ4hjC9keNHRWQul6O1gIfLdZBamOpWGGQnjsHmd38lEqtxpPS0sjzPuRvjc9bg1zW0TOGslABZyt_Ura0xNr2aLFq8DTgP5F9cAKE-vSPuyhRAcj0BzgnYuxbcYblj2OPkxF5AkLmzNI4M5Bs5VVfrkN5fnlof0JuCfa7ocvCZgS01OMm-iOxeoZNlLbQz6zqPvkgfJDdsih7wwfCxkkL9m-XkGdE1_GYvaRN12EkG2gXfiYF1AxiZkdihDhU-EjHXUYnZar2TXdhjtO6zjAxDV6Iezp_O0krCXrFu95-dV_4xjexjD2vuy3QDRbsBYun9NI-nH55U_sXS8ztdPhTAG03XPMwMZmPbu1cXUZKTNIHmYA6Qr0zPwTm-BkZfZvi9dnKLEtH2LfZKGOvG6FamjarxS7-spLVrswVhbPsWugjcxfJruzaoi6XjlrMXQo5qB0yXfML5gEQEHJQHPu35C5etR8VLiUv9M7kwj-ld-7FW2M1jz6T6KktxieJseZl_YzOUdgTazSfk4zGyc8J68NQ1hIQ-uJ0GgMYvU54WOr6n_pOBKMfL_BYcNSCOFBR0YXnisFtf-r1YpfKQ3ILUmpsxS1nnTKAK8VOO1LpaItUjLrk56p-xYgdQBhnJ9jZ8xpsb7yoQqsTsug8LVn01yVyYihj2Bf6LmCsFpoDMTkN1Or491xaN0m-g4SpUPsyBPnmYvUhfUhPUw4eYXLAImWm6OxSN3cGSk3AKmt1kMRlW-ZLgAO26ecQSuYMUHhM4nJhV-aab62YEfXVB9B_nF7zPEgDS2uS7RlwIR2e-cgjzl_Lmm4pDGcvDyxp_Z7daYODMdJbwEdvE65U69K2Z_HMDLvl6Pc-jO-Y8-I5R4KMBlFuNf5i2b3RnTqRAVLwx2AJpLp55kysaGfpvH4s-9XPnRjZPjQVFIBZJtDAhJG790OsXSIxMh1nIHbyPPX7JKMVmiN_N3TeTZifEGin9IrSGPCi4z24Vn40T4MiYQEFs5vtLPoqiScm4fx9lnDUJY7F5IQn3OTU4K4XZFmm8eZkK7_gfNsylQ8aCn4GmK8X70NW4KR24eU29mt35-SCaxwYZYPopUFWo_LzyTrZug3AIqAc6AeUsU8mrK5A0rFGFboDGYHnnc-Q0Ffrnp4C64YS2E2jfe_-KfIjAwfEBigfghHhoBpX_RC5zLVoFrblJTjscgAgE6ZcVigmZPEAGMf4iQ5E8zTtrVYLlim12TEvRSNtro5wpZXgG0XuD-Qgja0V80dwfdL0QX3S_qre1d8Za43SqoZc5CEGTP98Po8GPIIpwD_006uB6qcvVVQW5BNw7KVRD48jcph3kXpGhzbkmDA5pDTfjWbbgYuFQetMdrrvGNrjr3.iLsHlasWc7GptHe5pdwD_Q"
}The zkPass RESTful API strives to provide a smooth user experience, but occasionally errors may occur. This section equips you with knowledge about potential error responses you might encounter.
{
"status": [http_status_code],
"status_code": [status_code],
"status_text": [error_message]
}Something went wrong. Contact the administrator if the error persists
Our system failed to create a new instance of the privacy app
500
CUSTOM_ERROR
[Custom message]
A specific error occurred that requires custom handling (message varies)
500
MISSING_APPS_CONFIG
Something went wrong. Contact the administrator if the error persists
The required configuration for privacy apps is not found or inaccessible
500
ERROR_LOCKING_SOCKET
Something went wrong. Contact the administrator if the error persists
Our system failed to establish exclusive access to the communication socket
500
ERROR_SENDING_TO_SOCKET
Something went wrong. Contact the administrator if the error persistsrver is not ready yet, please try again later
Our system failed to send data through the communication socket
500
ERROR_RECEIVING_FROM_SOCKET
Something went wrong. Contact the administrator if the error persists
Our system failed to receive data from the communication socket
500
ERROR_DESERIALIZING
Something went wrong. Contact the administrator if the error persists
Our system failed to parse the output data from the privacy app
400
INVALID_PARAMS
Invalid parameter(s).
The provided parameters don't meet the required format or validation rules for the app input
400
INVALID_PARAMS
Error serializing parameters
Our system failed to convert the provided parameters into the required format
404
INVALID_URL
Invalid URL
The requested privacy app endpoint or resource was not found in our system
500
ERROR_LOADING_APP
Something went wrong. Contact the administrator if the error persists
Our system failed to initialize or load the requested privacy app
500
ERROR_LOADING_INSTANCE
privateKey
Read Generate Key Pair section for detail info.
We need to sign User Data and Data Verification Request (DVR) before sending a request to the zkPass service. This ensures that the payload is not tampered during transport.
Upload your publicKeyJWKS so that it's accessible from the internet. This will be used by zkPass service to verify the validity of the user data.
Example of the uploaded publicKeyJWKS
This is an example code of how you can sign a JSON object as JWS format in Typescript. Let's say you uploaded your publicKeyJWKS to https://mywebsite/my-keys.json
Example for User Data
Below is the example of Query in DVR, this query will be included in full DVR
Below is the example of full DVR that will be generated into DVR Token
After this section you should have :
User Data Token : User Data in JSON Web Signature (JWS) format.
DVR Token : DVR in JSON Web Signature (JWS) format.
Here's the example of User Data Token & DVR Token in JWS format.
{
"keys": [
{
"x": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELOmrNI4A9ML4iGJXpYlaZiYGVCxB",
"y": "k+evjhOZEbCLj17o/ZdfEv7dUZIRKRoZ1bud5Gq8OCItDlXkTyMrtWrhdA==",
"kid": "q6ZFSOJcTiZWJWkvUshpFw5v20xstZN/T4lt4zpKsUg="
}
]
}import { SignJWT, importPKCS8 } from "jose";
async signDataToJwsToken(
privateKey: string,
userDataOrDVR: any
): Promise<string> {
const verifyingKeyJwks = {
jku: "https://mywebsite/my-keys.json",
kid: "q6ZFSOJcTiZWJWkvUshpFw5v20xstZN/T4lt4zpKsUg="
}
const alg = "ES256";
const importedPrivateKey = await importPKCS8(privateKey, alg);
return await new SignJWT({ data: userDataOrDVR })
.setProtectedHeader({
alg: alg,
jku: verifyingKeyJwks.jku,
kid: verifyingKeyJwks.kid,
})
.sign(importedPrivateKey);
}{
"testID": "SCREEN-7083-12345",
"testName": "QualityHealth Comprehensive Screen",
"testDate": "2023-08-27T14:00:00Z",
"lab": {
"name": "QualityHealth Labs",
"ID": "QH801874",
"address": "1234 Elm St, Oakland, USA"
},
"subject": {
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1985-12-12",
"bloodType": "A+",
"DNAInfo": {
"markers": {
"APOE": ["E3", "E3"],
"BRCA1": "Normal",
"MTHFR": ["C677T", "A1298C"]
},
"haplogroups": {
"paternal": "R1b1",
"maternal": "H1a1"
}
},
"contact": {
"email": "jane.doe@gmail.com",
"phone": "650-555-1234"
},
"address": {
"street": "789 Oak Street",
"city": "San Jose",
"state": "CA",
"zip": "95134"
}
},
"measuredPanelsNgML": {
"amphetamines": 0,
"cocaine": 8,
"opiates": 102,
"benzodiazepines": 0
}
}[
{
"assign": {
"blood_test_status": {
"and": [
{
"==": [{ "dvar": "lab.ID" }, "QH801874"]
},
{
"==": [{ "dvar": "testID" }, "SCREEN-7083-12345"]
},
{
"~==": [{ "dvar": "subject.firstName" }, "jane"]
},
{
"~==": [{ "dvar": "subject.lastName" }, "doe"]
},
{
"==": [{ "dvar": "subject.dateOfBirth" }, "1985-12-12"]
},
{
"==": [{ "dvar": "measuredPanelsNgML.amphetamines" }, 0]
},
{
"<=": [{ "dvar": "measuredPanelsNgML.cocaine" }, 10]
}
]
}
}
},
{ "output": { "result": { "lvar": "blood_test_status" } } }
]{
"zkvm": "r0",
"dvr_title": "My DVR",
"dvr_id": "d5bba9dc-e90c-456d-811c-79aa73755f54",
"query_engine_ver": "1.3.0",
"query_method_ver": "24555fe163e523bb313df8355ca39fbd79d49a02c642373b19c2a31cfc7a78d",
"query": "[{\"assign\":{\"blood_test_status\":{\"and\":[{\"==\":[{\"dvar\":\"lab.ID\"},\"QH801874\"]},{\"==\":[{\"dvar\":\"testID\"},\"SCREEN-7083-12345\"]},{\"~\":[{\"dvar\":\"subject.firstName\"},\"jane\"]},{\"~\":[{\"dvar\":\"subject.lastName\"},\"doe\"]},{\"==\":[{\"dvar\":\"subject.dateOfBirth\"},\"1985-12-12\"]},{\"==\":[{\"dvar\":\"subject.contact.email\"},\"jane.doe@gmail.com\"]},{\"==\":[{\"dvar\":\"measuredPanelsNgML.amphetamines\"},0]},{\"<=\":[{\"dvar\":\"measuredPanelsNgML.cocaine\"},10]}]}}},{\"output\":{\"name\":{\"dvar\":\"subject.firstName\"}}},{\"output\":{\"email\":{\"dvar\":\"subject.contact.email\"}}},{\"output\":{\"result\":{\"lvar\":\"blood_test_status\"}}}]",
"user_data_requests": [
{
"key": "",
"value": {
"jku": "https://raw.githubusercontent.com/gl-zkPass/zkpass-sdk/main/docs/zkpass/sample-jwks/issuer-key.json",
"kid": "k-1"
}
}
],
"dvr_verifying_key": {
"jku": "https://raw.githubusercontent.com/gl-zkPass/zkpass-sdk/main/docs/zkpass/sample-jwks/verifier-key.json",
"kid": "k-1"
}
}{
"userDataToken": "eyJ0eXAiOiJKV1QiLCJqa3UiOiJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZ2wtemtQYXNzL3prcGFzcy1zZGsvbWFpbi9kb2NzL3prcGFzcy9zYW1wbGUtandrcy9pc3N1ZXIta2V5Lmpzb24iLCJraWQiOiJrLTEiLCJhbGciOiJFUzI1NiJ9.eyJkYXRhIjp7InRlc3RJRCI6IlNDUkVFTi03MDgzLTEyMzQ1IiwidGVzdE5hbWUiOiJRdWFsaXR5SGVhbHRoIENvbXByZWhlbnNpdmUgU2NyZWVuIiwidGVzdERhdGUiOiIyMDIzLTA4LTI3VDE0OjAwOjAwWiIsImxhYiI6eyJuYW1lIjoiUXVhbGl0eUhlYWx0aCBMYWJzIiwiSUQiOiJRSDgwMTg3NCIsImFkZHJlc3MiOiIxMjM0IEVsbSBTdCwgT2FrbGFuZCwgVVNBIn0sInN1YmplY3QiOnsiZmlyc3ROYW1lIjoiSmFuZSIsIl9maXJzdE5hbWVfemtwYXNzX3B1YmxpY18iOnRydWUsImxhc3ROYW1lIjoiRG9lIiwiZGF0ZU9mQmlydGgiOiIxOTg1LTEyLTEyIiwiYmxvb2RUeXBlIjoiQSsiLCJETkFJbmZvIjp7Im1hcmtlcnMiOnsiQVBPRSI6WyJFMyIsIkUzIl0sIkJSQ0ExIjoiTm9ybWFsIiwiTVRIRlIiOlsiQzY3N1QiLCJBMTI5OEMiXX0sImhhcGxvZ3JvdXBzIjp7InBhdGVybmFsIjoiUjFiMSIsIm1hdGVybmFsIjoiSDFhMSJ9fSwiY29udGFjdCI6eyJlbWFpbCI6ImphbmUuZG9lQGdtYWlsLmNvbSIsIl9lbWFpbF96a3Bhc3NfcHVibGljXyI6dHJ1ZSwicGhvbmUiOiI2NTAtNTU1LTEyMzQifSwiYWRkcmVzcyI6eyJzdHJlZXQiOiI3ODkgT2FrIFN0cmVldCIsImNpdHkiOiJTYW4gSm9zZSIsInN0YXRlIjoiQ0EiLCJ6aXAiOiI5NTEzNCJ9fSwibWVhc3VyZWRQYW5lbHNOZ01MIjp7ImFtcGhldGFtaW5lcyI6MCwiY29jYWluZSI6OCwib3BpYXRlcyI6MTAyLCJiZW56b2RpYXplcGluZXMiOjB9fX0.TwoIFlHXnKjhKGlhW6tCfuc20pgvFFUmZ_wEMBvrQyKaub7aN3SBT0_zPPeDn_EUi2UP6eo0pr7ofNjfXEtgsA",
"dvrToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJkYXRhIjp7Inprdm0iOiJyMCIsImR2cl90aXRsZSI6Ik15IERWUiIsImR2cl9pZCI6ImQ1YmJhOWRjLWU5MGMtNDU2ZC04MTFjLTc5YWE3Mzc1NWY1NCIsInF1ZXJ5IjoiW3tcImFzc2lnblwiOntcImJsb29kX3Rlc3Rfc3RhdHVzXCI6e1wiYW5kXCI6W3tcIj09XCI6W3tcImR2YXJcIjpcImxhYi5JRFwifSxcIlFIODAxODc0XCJdfSx7XCI9PVwiOlt7XCJkdmFyXCI6XCJ0ZXN0SURcIn0sXCJTQ1JFRU4tNzA4My0xMjM0NVwiXX0se1wifj09XCI6W3tcImR2YXJcIjpcInN1YmplY3QuZmlyc3ROYW1lXCJ9LFwiamFuZVwiXX0se1wifj09XCI6W3tcImR2YXJcIjpcInN1YmplY3QubGFzdE5hbWVcIn0sXCJkb2VcIl19LHtcIj09XCI6W3tcImR2YXJcIjpcInN1YmplY3QuZGF0ZU9mQmlydGhcIn0sXCIxOTg1LTEyLTEyXCJdfSx7XCI9PVwiOlt7XCJkdmFyXCI6XCJzdWJqZWN0LmNvbnRhY3QuZW1haWxcIn0sXCJqYW5lLmRvZUBnbWFpbC5jb21cIl19LHtcIj09XCI6W3tcImR2YXJcIjpcIm1lYXN1cmVkUGFuZWxzTmdNTC5hbXBoZXRhbWluZXNcIn0sMF19LHtcIjw9XCI6W3tcImR2YXJcIjpcIm1lYXN1cmVkUGFuZWxzTmdNTC5jb2NhaW5lXCJ9LDEwXX1dfX19LHtcIm91dHB1dFwiOntcIm5hbWVcIjp7XCJkdmFyXCI6XCJzdWJqZWN0LmZpcnN0TmFtZVwifX19LHtcIm91dHB1dFwiOntcImVtYWlsXCI6e1wiZHZhclwiOlwic3ViamVjdC5jb250YWN0LmVtYWlsXCJ9fX0se1wib3V0cHV0XCI6e1wicmVzdWx0XCI6e1wibHZhclwiOlwiYmxvb2RfdGVzdF9zdGF0dXNcIn19fV0iLCJxdWVyeV9lbmdpbmVfdmVyIjoiMS4zLjAiLCJxdWVyeV9tZXRob2RfdmVyIjoiMjQ1NTVmZTE2M2U1MjNiYjMxM2RmODM1NWNhMzlmYmQ3OWQ0OWEwMmM2NDIzNzNiMTljMmEzMWNmYzdhNzhkIiwidXNlcl9kYXRhX3JlcXVlc3RzIjp7IiI6eyJ1c2VyX2RhdGFfdXJsIjpudWxsLCJ1c2VyX2RhdGFfdmVyaWZ5aW5nX2tleSI6eyJLZXlzZXRFbmRwb2ludCI6eyJqa3UiOiJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZ2wtemtQYXNzL3prcGFzcy1zZGsvbWFpbi9kb2NzL3prcGFzcy9zYW1wbGUtandrcy9pc3N1ZXIta2V5Lmpzb24iLCJraWQiOiJrLTEifX19fSwiZHZyX3ZlcmlmeWluZ19rZXkiOnsiS2V5c2V0RW5kcG9pbnQiOnsiamt1IjoiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2dsLXprUGFzcy96a3Bhc3Mtc2RrL21haW4vZG9jcy96a3Bhc3Mvc2FtcGxlLWp3a3MvdmVyaWZpZXIta2V5Lmpzb24iLCJraWQiOiJrLTEifX19fQ.3sGHmQZ_lbEJei9OKTxlshDoYs2wWurjEyiA767BEBrxU5u5fSV-s1qHghVlp748MqZf_cLb7j6g3MrsL34wbw"
}