-
Notifications
You must be signed in to change notification settings - Fork 14
FIDO2: Conformance testing server API
FIDO Alliance Certification Conformance Test Tools require companies to implement a standardised API for the conformance testing purpose.
- Introduction
-
Registration
- Overview
- Examples
- Credential Creation Options
- Authenticator Attestation Response
- Primary IDL
- ServerPublicKeyCredentialCreationOptionsRequest
- ServerPublicKeyCredentialCreationOptionsResponse
- ServerAuthenticatorAttestationResponse
- Supporting IDL
- ServerPublicKeyCredential
- ServerPublicKeyCredentialUserEntity
- ServerPublicKeyCredentialDescriptor
-
Authentication
- Overview
- Examples
- Credential Get Options
- Authenticator Assertion Response
- IDL
- ServerPublicKeyCredentialGetOptionsRequest
- ServerPublicKeyCredentialGetOptionsResponse
- ServerAuthenticatorAssertionResponse
-
Common
- IDL
- ServerResponse
- IDL
This document contains a non-normative, proposed REST API for FIDO2 servers. While this interface is not required, it is the interface that is used for the FIDO2 conformance test tools so that servers can receive and send messages in a standard way for those messages to be validated by the conformance test tools.
As with the FIDO2 specifications, the interfaces described here are highly dependent on the !WebAuthn specification. The nomenclature of this document follows that of WebAuthn and reuses the Interface Definition Language (IDL) for defining the messages that are sent to / from the server.
This document is broken up into three sections: registration, authentication, and common. The registration and authentication sections contain the messages relevant to those operations, and the common section includes messages and data formats that are common to both registration and authentication.
This section includes a brief overview of the registration messages that are exchanged between a client and the server, followed by examples of those messages, and concluding with IDL definitions of the messages. Note that registration is also referred to as "credential creation" due to the WebAuthn nomenclature.
The registration flow takes part in two steps for a total of four messages. The first step is that a client retrieves "Credential Creation Options", which involves the client sending a ServerPublicKeyCredentialCreationOptionsRequest
to the server and the server responding with a ServerPublicKeyCredentialCreationOptionsResponse
. These options are intended to be used with WebAuthn's navigator.credentials.create(), especially the challenge which necessarily is generated by the server for the sake of Man in the Middle (MITM) protection. Upon completion of navigator.credentials.create()
the dictionary that is created from that call is sent back to the server as the ServerPublicKeyCredential
with response
field set to ServerAuthenticatorAttestationResponse
. Note that the ServerAuthenticatorAttestationResponse
extends the generic ServerAuthenticatorResponse
, which is described in the Common section below. The server will validate challenges, origins, signatures and the rest of the ServerAuthenticatorAttestationResponse
according to the algorithm described in section 7.1 of the [Webauthn] specs, and will respond with the appropriate ServerResponse
message.
Request:
- URL: /attestation/options
-
Method:
POST
- URL Params: None
-
Body:
application/json
formattedServerPublicKeyCredentialCreationOptionsRequest
{
"username": "[email protected]",
"displayName": "John Doe",
"authenticatorSelection": {
"requireResidentKey": false,
"authenticatorAttachment": "cross-platform",
"userVerification": "preferred"
},
"attestation": "direct"
}
Success Response:
-
HTTP Status Code:
200 OK
-
Body:
application/json
formattedServerPublicKeyCredentialCreationOptionsResponse
{
"status": "ok",
"errorMessage": "",
"rp": {
"name": "Example Corporation"
},
"user": {
"id": "S3932ee31vKEC0JtJMIQ",
"name": "[email protected]",
"displayName": "John Doe"
},
"challenge": "uhUjPNlZfvn7onwuhNdsLPkkE5Fv-lUN",
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
}
],
"timeout": 10000,
"excludeCredentials": [
{
"type": "public-key",
"id": "opQf1WmYAa5aupUKJIQp"
}
],
"authenticatorSelection": {
"requireResidentKey": false,
"authenticatorAttachment": "cross-platform",
"userVerification": "preferred"
},
"attestation": "direct"
}
Error Response:
-
HTTP Status Code:
4xx or 5xx
-
Body:
application/json
formattedServerResponse
{
"status": "failed",
"errorMessage": "Missing challenge field!"
}
Sample JavaScript:
fetch('/attestation/options', {
method : 'POST',
credentials : 'same-origin',
headers : {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
"username": "[email protected]",
"displayName": "John Doe",
"authenticatorSelection": {
"requireResidentKey": false,
"authenticatorAttachment": "cross-platform",
"userVerification": "preferred"
},
"attestation": "direct"
})
}).then(function (response) {
return response.json();
}).then(function (json) {
console.log(json);
}).catch(function (err) {
console.log({ 'status': 'failed', 'error': err });
})
Request:
- URL: /attestation/result
-
Method:
POST
- URL Params: None
-
Body:
application/json
formattedServerPublicKeyCredential
withresponse
field set toServerAuthenticatorAttestationResponse
{
"id": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
"response": {
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
"attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"
},
"type": "public-key"
}
Success Response:
-
HTTP Status Code:
200 OK
-
Body:
application/json
formattedServerResponse
{
"status": "ok",
"errorMessage": ""
}
Error Response:
-
HTTP Status Code:
4xx or 5xx
-
Body:
application/json
formattedServerResponse
{
"status": "failed",
"errorMessage": "Can not validate response signature!"
}
Sample Call:
fetch('/attestation/result', {
method : 'POST',
credentials : 'same-origin',
headers : {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
"id": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
"response": {
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
"attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"
},
"type": "public-key"
})
}).then(function (response) {
return response.json();
}).then(function (json) {
console.log(json);
}).catch(function (err) {
console.log({ 'status': 'failed', 'error': err });
})
dictionary ServerPublicKeyCredentialCreationOptionsRequest {
required DOMString username;
required DOMString displayName;
AuthenticatorSelectionCriteria authenticatorSelection;
AttestationConveyancePreference attestation = "none";
};
-
required
username
- A human-readable name for the entity. For example, "alexm", "[email protected]" or "+14255551234". -
required
displayName
- A human-friendly name for the user account, intended only for display. For example, "Alex P. Müller" or "田中 倫". -
authenticatorSelection
- a dictionary containing AuthenticatorSelectionCriteria described in WebAuthn specification -
attestation
- can be set to "none", "indirect", "direct". More in WebAuthn specification. Default set to none
dictionary ServerPublicKeyCredentialCreationOptionsResponse : ServerResponse {
required PublicKeyCredentialRpEntity rp;
required ServerPublicKeyCredentialUserEntity user;
required DOMString challenge;
required sequence<PublicKeyCredentialParameters> pubKeyCredParams;
unsigned long timeout;
sequence<ServerPublicKeyCredentialDescriptor> excludeCredentials = [];
AuthenticatorSelectionCriteria authenticatorSelection;
AttestationConveyancePreference attestation = "none";
AuthenticationExtensionsClientInputs extensions;
};
- required
rp
- a dictionary defined as PublicKeyCredentialRpEntity described in WebAuthn specification - required
user
- a dictionary defined as ServerPublicKeyCredentialUserEntity, described in this document - required
challenge
- a random base64url encoded challenge, that is minimum 16 bytes long, and maximum 64 bytes long - required
pubKeyCredParams
- sequence of PublicKeyCredentialParameters described in WebAuthn specification -
timeout
- timeout(ms) -
excludeCredentials
- a sequence of ServerPublicKeyCredentialDescriptor described in this document -
authenticatorSelection
- a dictionary set AuthenticatorSelectionCriteria described in WebAuthn specification -
attestation
- can be set to "none", "indirect", "direct". More in WebAuthn specification. Default set to none -
extensions
- a dictionary set to AuthenticationExtensionsClientInputs described in WebAuthn specs - Extends ServerResponse described in this document
Generally the same as AuthenticatorAttestationResponse from WebAuthn, but uses base64url
encoding for fields that were of type BufferSource
.
dictionary ServerAuthenticatorAttestationResponse : ServerAuthenticatorResponse {
required DOMString clientDataJSON;
required DOMString attestationObject;
};
- required
clientDataJSON
- base64url encoded clientDataJSON buffer - required
attestationObject
- base64url encoded attestationObject buffer
Generally the same as PublicKeyCredential from WebAuthn, but uses base64url
formatting for fields that are defined as BufferSource
in WebAuthn.
dictionary ServerPublicKeyCredential : Credential {
required DOMString type;
required DOMString id;
required ServerAuthenticatorResponse response;
AuthenticationExtensionsClientOutputs getClientExtensionResults;
};
- required
id
- This attribute is inherited from Credential, though ServerPublicKeyCredential overrides it with base64url encoding of the authenticator credId - required
response
- a dictionary defined as ServerAuthenticatorAttestationResponse or by ServerAuthenticatorAssertionResponse, described in this document - required
type
- This attribute is inherited from Credential, though ServerPublicKeyCredential overrides it with "public-key" -
getClientExtensionResults
- a map containing extension identifier, which contain client extension output entries produced by the extension’s client extension processing. - Extends Credential described in Credential Management API specification
Generally the same as the PublicKeyCredentialUserEntity from WebAuthn, but uses base64url
formatting instead of BufferSource
for id
.
dictionary ServerPublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
required DOMString id;
required DOMString displayName;
};
- required
id
- base64url encoded id buffer - required
displayName
- A human-friendly name for the user account, intended only for display. For example, "Alex P. Müller" or "田中 倫". Corresponding to ServerPublicKeyCredentialCreationOptionsRequest.displayName - Extends PublicKeyCredentialEntity described in WebAuthn specification
Generally the same as PublicKeyCredentialDescriptor from WebAuthn, but uses base64url
formatting instead of BufferSource
for id
.
dictionary ServerPublicKeyCredentialDescriptor {
required PublicKeyCredentialType type;
required DOMString id;
sequence<AuthenticatorTransport> transports;
};
- required
type
- a dictionary defined as PublicKeyCredentialType described in WebAuthn specification - required
id
- contains base64url encoded credential ID of the public key credential that the caller is referring to. - transports - a sequence of AuthenticatorTransport described in WebAuthn specification
This section starts with an overview of the messages exchanged with the server for authentication, then proceeds to show examples of those messages, and concludes with the specific IDL definitions of those messages. Note that "authentication" is sometimes referred to as "getting credentials", a "credential request", or "getting an authentication assertion" due to the terminology used in WebAuthn.
Similar to the communication flow described for Registration, the Authentication flow requires four messages to be exchanged with the server. The first pair of messages are a request from the client to the server in the format of ServerPublicKeyCredentialGetOptionsRequest
and the server returns a corresponding ServerPublicKeyCredentialGetOptionsResponse
to the client. This ServerPublicKeyCredentialGetOptionsResponse
is intended to be used as the parameters to the WebAuthn navigator.credentials.get()
call. The results of navigator.credentials.get()
are formatted by the client in to a ServerPublicKeyCredential
with response
field set to ServerAuthenticatorAssertionResponse
and sent to the server. The server validates the assertion according the section 7.2 of the [WebAuthn] specification, and returns the corresponding ServerResponse
.
Request:
- URL: /attestation/options
-
Method:
POST
- URL Params: None
-
Body:
application/json
encodedServerPublicKeyCredentialGetOptionsRequest
{
"username": "[email protected]",
"userVerification": "required"
}
Success Response:
-
HTTP Status Code:
200 OK
-
Body:
application/json
encodedServerPublicKeyCredentialGetOptionsResponse
{
"status": "ok",
"errorMessage": "",
"challenge": "6283u0svT-YIF3pSolzkQHStwkJCaLKx",
"timeout": 20000,
"rpId": "example.com",
"allowCredentials": [
{
"id": "m7xl_TkTcCe0WcXI2M-4ro9vJAuwcj4m",
"type": "public-key"
}
],
"userVerification": "required"
}
Error Response:
-
HTTP Status Code:
4xx or 5xx
-
Body:
application/json
encodedServerResponse
{
"status": "failed",
"errorMessage": "User does not exists!"
}
Sample Call:
fetch('/attestation/options', {
method : 'POST',
credentials : 'same-origin',
headers : {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
"username": "[email protected]",
"userVerification": "required"
})
}).then(function (response) {
return response.json();
}).then(function (json) {
console.log(json);
}).catch(function (err) {
console.log({ 'status': 'failed', 'error': err });
})
Request:
- URL: /assertion/result
-
Method:
POST
- URL Params: None
-
Body:
application/json
encodedServerPublicKeyCredential
withresponse
field set toServerAuthenticatorAssertionResponse
{
"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
"response":{
"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA",
"signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL",
"userHandle":"",
"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"
},
"type":"public-key"
}
Success Response:
-
HTTP status code:
200 OK
-
Body:
application/json
encodedServerResponse
{
"status": "ok",
"errorMessage": ""
}
Error Response:
-
HTTP status code:
4xx or 5xx
-
Body:
application/json
encodedServerResponse
{
"status": "failed",
"errorMessage": "Can not validate response signature!"
}
Sample Call:
fetch('/assertion/result', {
method : 'POST',
credentials : 'same-origin',
headers : {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
"response":{
"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA",
"signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL",
"userHandle":"",
"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"
},
"type":"public-key"
})
}).then(function (response) {
return response.json();
}).then(function (json) {
console.log(json);
}).catch(function (err) {
console.log({ 'status': 'failed', 'error': err });
})
dictionary ServerPublicKeyCredentialGetOptionsRequest {
required DOMString username;
UserVerificationRequirement userVerification = "preferred";
};
-
required
username
- A human-readable name for the entity. For example, "alexm", "[email protected]" or "+14255551234". -
userVerification
- can be set to "required", "preferred", "discouraged". More in WebAuthn specification. Default set to "preferred"
dictionary ServerPublicKeyCredentialGetOptionsResponse : ServerResponse {
required DOMString challenge;
unsigned long timeout;
USVString rpId;
sequence<ServerPublicKeyCredentialDescriptor> allowCredentials = [];
UserVerificationRequirement userVerification = "preferred";
AuthenticationExtensionsClientInputs extensions;
};
- required
challenge
- a random base64url encoded challenge, that is minimum 16 bytes long, and maximum 64 bytes long -
timeout
- timeout(ms) -
rpId
- This optional member specifies the relying party identifier claimed by the caller. If omitted, its value will be the CredentialsContainer object’s relevant settings object's origin's effective domain. -
allowCredentials
- a sequence of ServerPublicKeyCredentialDescriptor described in this document -
userVerification
- can be set to "required", "preferred", "discouraged". More in WebAuthn specification. Default set to "preferred". Corresponds to ServerPublicKeyCredentialGetOptionsRequest.userVerification -
extensions
- a dictionary set to AuthenticationExtensionsClientInputs described in WebAuthn specs - Extends ServerResponse described in this document
dictionary ServerAuthenticatorAssertionResponse : ServerAuthenticatorResponse {
required DOMString clientDataJSON;
required DOMString authenticatorData;
required DOMString signature;
required DOMString userHandle;
};
- required
clientDataJSON
- base64url encoded clientDataJSON buffer - required
authenticatorData
- base64url encoded authenticatorData buffer - required
signature
- base64url encoded signature buffer - required
userHandle
- base64url encoded userHandle buffer. Corresponding to registered user ServerPublicKeyCredentialUserEntity.id
dictionary ServerResponse {
required Status status;
required DOMString errorMessage = "";
}
- required
status
- Describing the status of the response. Can be set to either "ok" or "failed". - required
errorMessage
- Ifstatus
is set to "failed" this field MUST NOT be empty