Operations Services
Mobile token API is based on the concept of an “operation”. Operation is an activity that user needs to review and either approve or reject via the mobile token app. Each operation has a unique “operation ID” that can be used to obtain information about that particular operation and poll for the operation status.
Operations are created based on a “template” (registered in the system) that is filled with specific parameters.
Template represents a type of an operation, parameters assign the particular operation properties. This way, you can
create an operation, for example, for a payment (payment
template, to initiate authorize_payment
operation type)
with a particular amount (passed in the parameters.amount
and parameters.currency
field).
Possible Error Codes
Error Code | HTTP Status Code | Description |
---|---|---|
ERROR_REGISTRATION_NOT_FOUND |
400 |
Indicates that no registration is found for the provided user or the user does not have access to the registrations. |
ERROR_OPERATION_NOT_FOUND |
400 |
Indicates that an operation with the provided ID was not found. |
ERROR_OPERATION_STATE_CHANGE |
400 |
Indicates that the operation’s state does not allow the requested action, for example, cancelling an already expired operation. |
ERROR_OTP_INVALID |
400 |
Indicates a failure in OTP verification due to an invalid OTP format. |
HTTP_401 |
401 |
Unauthorized access attempt. This occurs when invalid credentials are provided. |
ERROR_INTERNAL_API |
500 |
An internal server error occurred, potentially due to misconfiguration. Check your deployment configuration for errors. |
Services
post /v2/operations Create New Operation
Create a new operation to be approved.
Request
{
"userId": "$USER_ID",
"template": "$TEMPLATE",
"language": "en",
"externalId": "$EXTERNAL_ID",
"flag": "$FLAG",
"timestampExpires": "$TIMESTAMP_EXPIRES",
"parameters": {
"param1": "$PARAM1",
"param2": "$PARAM2",
"param3": "$PARAM3"
},
"proximityCheckEnabled": true,
"silent": false
}
Attribute | Type | Description |
---|---|---|
userId |
String |
ID of a user for whom to create a new operation. Use null value for non-personalized operations. |
template * |
String |
Template to use for the particular operation. |
language |
char[2] |
Language code to be used for this operation. Default: en |
externalId |
String |
ID of the operation in some external system, for example, an ID of the transaction. |
flag |
String |
Activation flag which limits scope of the operation to activations marked with specified flag. |
timestampExpires |
Long |
Unix timestamp in milliseconds, represents when the operation will expire, overrides expiration period from operation template. |
parameters |
Map<String, String> |
Parameters of the particular operation. The keys used in the map depend on the specific operation template, there is no limitation on the count. However, we recommend using reasonable amount (i.e., up-to 5) of parameters. |
proximityCheckEnabled |
Boolean |
Optional parameter, whether proximity check should be used. Overrides configuration from operation template. |
silent |
Boolean |
Optional parameter, whether to suppress push notifications. |
Response
{
"operationId": "$OPERATION_ID",
"userId": "$USER_ID",
"externalId": "$EXTERNAL_ID",
"status": "PENDING",
"operationType": "$OPERATION_TYPE",
"flag": "$FLAG",
"parameters": {
"param1": "$PARAM1",
"param2": "$PARAM2",
"param3": "$PARAM3"
},
"failureCount": 0,
"maxFailureCount": 5,
"timestampCreated": 1617787702781,
"timestampExpires": 1617788002781,
"timestampFinalized": null,
"proximityOtp": "123456",
"registrationId": "$REGISTRATION_ID"
}
Attribute | Type | Description |
---|---|---|
operationId * |
UUID |
ID of the just created operation. |
userId * |
String |
ID of the user who created the operation. |
externalId |
String |
ID of the operation in some external system, for example, an ID of the transaction. |
status * |
String |
For just created operation, PENDING value is always returned. See operation states in GET /operations . |
template * |
String |
The template that was used to create the operation. |
operationType * |
String |
The operation type, created according to provided template. |
flag |
String |
Activation flag which limits scope of the operation to activations marked with specified flag. |
parameters |
Map<String, String> |
Parameters used while creating the operation. |
failureCount * |
Long |
How many failed approval attempts user made (always 0 for a newly created operation). |
maxFailureCount * |
Long |
How many failed approval attempts are allowed for this operation. |
timestampCreated * |
Long |
Unix timestamp in milliseconds, represents when the operation was created. |
timestampExpires * |
Long |
Unix timestamp in milliseconds, represents when the operation will expire. |
timestampFinalized |
Long |
Unix timestamp in milliseconds, represents when the operation was finished. Note that expiration of operation does not set the timestamp - if the operation is expired, look for timestampExpires value. |
proximityOtp |
String |
TOTP for proximity check (if enabled) valid for the current time step. |
registrationId |
String |
Registration Id of the device scoped for the operation. The value is set only if the operation is scoped to device. |
Operation could not be created due to a business logic problem.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_REGISTRATION_NOT_FOUND",
"message": "No active registration found matching operation criteria"
}
}
Possible error states are:
ERROR_REGISTRATION_NOT_FOUND
- No registration is found for provided user or user does not have access to the registrations.
Invalid username or password was provided while calling the service.
{
"status": "ERROR",
"responseObject": {
"code": "HTTP_401",
"message": "Unauthorized"
}
}
Error occurred while calling the internal service. This can happen only as a result of misconfiguration. Check your deployment configuration for errors.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_INTERNAL_API",
"message": "Unable to call upstream service"
}
}
get /v2/operations/{operationId} Get Operation Status
Get the status of the operation by operation ID.
Request
Path Params
Param | Type | Description |
---|---|---|
operationId |
UUID |
ID of an operation to obtain status for. |
userId |
String |
Optional user identifier for operation claim. |
Response
{
"operationId": "$OPERATION_ID",
"userId": "$USER_ID",
"status": "PENDING",
"operationType": "$OPERATION_TYPE",
"flag": "$FLAG",
"parameters": {
"param1": "$PARAM1",
"param2": "$PARAM2",
"param3": "$PARAM3"
},
"additionalData": {
"activationId": "$ACTIVATION_ID",
"ipAddress": "172.168.240.48",
"userAgent": "PowerAuthNetworking/1.3.0 (en; wifi) com.wultra.app.MobileToken/2.0.0 (Apple; iOS/17.3.1; iphone16,1)",
"device": {
"networkVersion": "1.3.0",
"language": "en",
"connection": "wifi",
"product": "com.wultra.app.MobileToken",
"version": "2.0.0",
"platform": "Apple",
"os": "iOS",
"osVersion": "17.3.1",
"model": "iphone16,1"
}
},
"failureCount": 0,
"maxFailureCount": 5,
"timestampCreated": 1617787702781,
"timestampExpires": 1617788002781,
"timestampFinalized": 1617788002781,
"proximityOtp": "123456",
"registrationId": "$REGISTRATION_ID"
}
Attribute | Type | Description |
---|---|---|
operationId * |
UUID |
ID of the just created operation. |
userId |
String |
ID of the user who created the operation. |
status * |
String |
For just created operation, “PENDING” value is always returned. See operation states in GET /operations . |
statusReason |
String |
Optional details why the status has changed. The value should be sent in the form of a computer-readable code, not a free-form text. |
template * |
String |
The template that was used to create the operation. |
operationType * |
String |
The operation type, created according to provided template. |
flag |
String |
Activation flag which limits scope of the operation to activations marked with specified flag. |
parameters |
Map<String, String> |
Parameters used while creating the operation. |
additionalData |
Map<String, Object> |
Additional data stored within the operation, such as activation identifier used for approving the operation or information about the device relevant to the operation. |
failureCount * |
Long |
How many failed approval attempts user made. |
maxFailureCount * |
Long |
How many failed approval attempts are allowed for this operation. |
timestampCreated * |
Long |
Unix timestamp in milliseconds, represents when the operation was created. |
timestampExpires * |
Long |
Unix timestamp in milliseconds, represents when the operation will expire. |
timestampFinalized |
Long |
Unix timestamp in milliseconds, represents when the operation was finished. Note that expiration of operation does not set the timestamp - if the operation is expired, look for timestampExpires value. |
proximityOtp |
String |
TOTP for proximity check (if enabled) valid for the current time step. |
registrationId |
String |
Registration Id of the device scoped for the operation. The value is set only if the operation is scoped to device. |
The possible operation states are:
PENDING
- Operation is active, waiting for the user’s action.CANCELED
- The operation was cancelled, for example, by clicking the “Cancel” button in the web interface.EXPIRED
- The operation expired.APPROVED
- The operation was approved by the user.REJECTED
- The operation was rejected by the user.FAILED
- The operation approval failed due to too many failed approval attempts.
Operation status could not be obtained due to a business logic problem.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_NOT_FOUND",
"message": "Operation with given ID was not found"
}
}
Possible error states are:
ERROR_REGISTRATION_NOT_FOUND
- User does not have access to the registrations.ERROR_OPERATION_NOT_FOUND
- Operation with provided ID was not found.
Invalid username or password was provided while calling the service.
{
"status": "ERROR",
"responseObject": {
"code": "HTTP_401",
"message": "Unauthorized"
}
}
Error occurred while calling the internal service. This can happen only as a result of misconfiguration. Check your deployment configuration for errors.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_INTERNAL_API",
"message": "Unable to call upstream service"
}
}
delete /v2/operations/{operationId} Cancel Operation
Delete the pending operation. The call checks the status of the operation and returns error in the case operation cannot be canceled (i.e., operation already expired).
Request
Path Params
Param | Type | Description |
---|---|---|
operationId * |
UUID |
ID of an operation to cancel. |
Query Params
Param | Type | Description |
---|---|---|
statusReason |
String |
Optional details why the status has changed. The value should be sent in the form of a computer-readable code, not a free-form text. |
Response
{
"status": "OK"
}
Attribute | Type | Description |
---|---|---|
status * |
String |
Fixed value OK . |
Operation could not be canceled due to a business logic problem.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_NOT_FOUND",
"message": "Operation with given ID was not found"
}
}
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_STATE_CHANGE",
"message": "Operation is in invalid state for requested action"
}
}
Possible error states are:
ERROR_REGISTRATION_NOT_FOUND
- User does not have access to the registrations.ERROR_OPERATION_NOT_FOUND
- Operation with provided ID was not found.ERROR_OPERATION_STATE_CHANGE
- Operation state does not allow canceling, i.e., operation already expired.
Invalid username or password was provided while calling the service.
{
"status": "ERROR",
"responseObject": {
"code": "HTTP_401",
"message": "Unauthorized"
}
}
Error occurred while calling the internal service. This can happen only as a result of misconfiguration. Check your deployment configuration for errors.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_INTERNAL_API",
"message": "Unable to call upstream service"
}
}
get /v2/operations/{operationId}/offline/qr Get Operation QR Code (Offline Approval)
Get the QR code for an offline approval of the particular operation. The user scans the QR code with the mobile device,
computes the OTP which is then validated via POST /v2/operations/{operationId}/offline/otp
call. The call also returns
the nonce
value, which is required during the OTP code verification later.
Tip: Store the nonce
value in the hidden form field on the page, next to the generated QR code and text field for
the OTP input.
Request
Path Params
Param | Type | Description |
---|---|---|
operationId * |
UUID |
ID of an operation to obtain QR code for. |
Query Params
Param | Type | Description |
---|---|---|
registrationId * |
String |
ID of registration for the device which is expected to read the QR code. |
Response
{
"operationQrCodeData": "b67a77d6-8308-4ffd-b6e0-9f42f36a41a7\nApprove Login\nPlease confirm the login request.\nA2\nB\n7YLYRMvRIX0GZD94/oGPjg==\n1MEQCIDh0mCFv9uKdE7Gec+dE4WRfwDLpMltCy4hSMqMo1FwxAiAJwmzrMa6QsWeFoZEvQgRZeBd6v7e4vVw84w2bsvT7+Q==",
"nonce": "7YLYRMvRIX0GZD94/oGPjg=="
}
Attribute | Type | Description |
---|---|---|
operationQrCodeData * |
String |
Contents of the QR code to be scanned by the mobile token app. |
nonce * |
String |
Cryptographic nonce, used during the OTP verification. |
Operation QR code for offline approvals could not be created due to business logic error.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_NOT_FOUND",
"message": "Operation with given ID was not found"
}
}
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_STATE_CHANGE",
"message": "Operation is in invalid state for requested action"
}
}
Possible error states are:
ERROR_REGISTRATION_NOT_FOUND
- Registration does not exist, it is not active or user does not have access to the registration.ERROR_OPERATION_NOT_FOUND
- Operation with provided ID was not found.ERROR_OPERATION_STATE_CHANGE
- Operation state does not allow obtaining the QR code, i.e., operation already expired.
Invalid username or password was provided while calling the service.
{
"status": "ERROR",
"responseObject": {
"code": "HTTP_401",
"message": "Unauthorized"
}
}
Error occurred while calling the internal service. This can happen only as a result of misconfiguration. Check your deployment configuration for errors.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_INTERNAL_API",
"message": "Unable to call upstream service"
}
}
post /v2/operations/{operationId}/offline/otp Verify Operation OTP (Offline Approval)
Verify operation OTP for offline operation approval. After the user scans the QR code with operation data, the mobile authenticator prompts the user for an authentication and calculates the OTP code. The user then rewrites the OTP in the web browser, into a form that stores operation ID and nonce values.
Tip: The OTP code is accepted in the “credit card number” format of 4x4 digits separated by a
dash (9301-7407-1055-2502
), as well as 2x8 digits separated by a dash ( 93017407-10552502
), or simply as 16
digits (9301740710552502
).
Request
Path Params
Param | Type | Description |
---|---|---|
operationId * |
UUID |
ID of an operation to validate OTP for. |
Request Params
{
"otp": "$OTP",
"nonce": "$NONCE",
"registrationId": "$REGISTRATION_ID"
}
Attribute | Type | Description |
---|---|---|
otp * |
String |
OTP value as entered by the user. |
nonce * |
String |
Cryptographic nonce obtained while creating the QR code. |
registrationId * |
String |
ID of registration of the device used for operation OTP verification. |
Response
{
"otpValid": true,
"userId": "test-user",
"operationId": "cb21daf7-8b06-4f88-8277-171fc1d5131e",
"registrationId": "b4c73d24-050f-4aaa-9fab-bda401079879",
"registrationStatus": "ACTIVE",
"signatureType": "POSSESSION_KNOWLEDGE",
"remainingAttempts": 5,
"flags": [
"FLAG1"
],
"application": {
"name": "APP1",
"roles": [
"ROLE1"
]
}
}
Attribute | Type | Description |
---|---|---|
otpValid * |
boolean | Whether offline OTP verification succeeded. |
userId * |
String |
Identifier of user who requested the signature verification. |
registrationId * |
String |
Identifier of registration used when verifying the signature. |
registrationStatus * |
String |
Registration status. |
signatureType * |
String |
PowerAuth signature type. |
remainingAttempts * |
Long |
Number of remaining attempts for signature verification. |
flags * |
String[] |
Registration flags. |
application.name * |
String |
Application name. |
application.roles * |
String[] |
Assigned application roles. |
Operation OTP code verification for offline approvals failed due to a business logic problem.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OTP_INVALID",
"message": "Operation OTP format is invalid, OTP validation skipped."
}
}
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_NOT_FOUND",
"message": "Operation with given ID was not found"
}
}
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_OPERATION_STATE_CHANGE",
"message": "Operation is in invalid state for requested action"
}
}
Possible error states are:
ERROR_OTP_INVALID
- OTP verification failed due to invalid OTP format.ERROR_REGISTRATION_NOT_FOUND
- User does not have access to the registration.ERROR_OPERATION_NOT_FOUND
- Operation with provided ID was not found.ERROR_OPERATION_STATE_CHANGE
- Operation state does not allow verifying the OTP, i.e., operation already expired.
Invalid username or password was provided while calling the service.
{
"status": "ERROR",
"responseObject": {
"code": "HTTP_401",
"message": "Unauthorized"
}
}
Error occurred while calling the internal service. This can happen only as a result of misconfiguration. Check your deployment configuration for errors.
{
"status": "ERROR",
"responseObject": {
"code": "ERROR_INTERNAL_API",
"message": "Unable to call upstream service"
}
}