Resources

Job Progress Messaging

Overview

CardSavr utilitizes a messaging system to "stream" messages to clients. Ideally, a job can process without any participation from the user, but occasionally some additional user input may be necessary. In these situations, client applications may need to acquire additional security credentials (MFA codes), they may need to fix incorrect credentials, and they may wish to be notified when jobs complete, pass authentication, or even fail. There are two kinds of messages.

Status Messages

Job status messages can either be acquired from the /messages/place_card_on_single_site_jobs or the /messages/cardholders endpoints. These messages contain the job_id, the current status, and the percent complete of the job. Once jobs complete they have a termination type which defines the final state of the job.

They may simply serve as a heartbeat to the client to ascertain that the job is still running. There is also a job_timeout value that lets the client know when a job is about to end, usually a result of waiting for credentials from the user. When you consume status messages, they can only be consumed once. Although you can always directly query the current status of a job via the jobs endpoint, old messages are not available.

typedescription
typethe type of message - this is currently always job_status
job_idthe job id for this message channel
messagea message containing data aboout this status
message.job_timeouttime left before this job times out (in seconds), it is appropriate to alert the cardholder a minute before their session expires. There is an initial timeout of 5 minutes for a job, but if additional information is required from the user, additional time is added to the length of the job. It is important to alert the user that time is about to expire while prompting for new credentials or a TFA code.
message.percent_completeapproximate percentage of the job that is completed.
message.statusthe status for this job (e.g. AUTH, UPDATING or DUPLICATE_CARD)
message.termination_type(only on the final message) - the exit state for this job (BILLABLE, USER_DATA_FAILURE, SITE_INTERACTION_FAILURE, PROCESS_FAILURE). The application should alert the clent upon receipt of one of these messages.
message.status_messagea status message that should be shown to the user

Examples:

{
  "type": "job_status",
  "job_id": 101,
  "message": {
    "status": "UPDATING",
    "percent_complete": 80,
    "auth_percent_complete": 100,
    "job_timeout": 827027,
    "status_message": "Updating your payment method. No further action required."
  }
}
{
  "type": "job_status",
  "job_id": 101,
  "message": {
    "status": "TIMEOUT_TFA",
    "percent_complete": 100,
    "auth_percent_complete": 100,
    "job_timeout": 827027,
    "status_message": "Unable to automatically update your card due to invalid or missing two-factor authentication.",
    "termination_type": "USER_DATA_FAILURE"
  }
}

Credential Requests

Unlike job status messages, credential requests persist until responded to. Each request has a type, and an envelope_id. This envelope_id must accompany each response. Credential requests have two types: tfa_request and credential_request. When a request is retrieved by the client, the user should either enter in new credentials or get a tfa response from their email, text message or sometimes even mobile apps. Once the server receives the credential response, the request is removed, and the job continues. (For backward compatibiliy, you can still key off the request_type: 'tfa_request' always requires a tfa response, and 'credential_request' always requires a username/password, but this functionality is deprecated and will not be supported after 6/1/2023)

typedescription
typethe type of message - tfa_request or credential_request (or other types, use account_link for credential request types)
job_idthe job_id for this message channel, this is important to know which merchant is requesting
envelope_ida guid which must be included in the response
account_linka list of proprerties that need to be collected from the client -- note that some properties are secret and should be obscured when entered

Examples:

{
  "type": "tfa_message",
  "job_id": 101,
  "envelope_id": “<GUID>”,
  "account_link": [
    {
      "key_name": "tfa_message",
      "label": "Please enter the code sent to your mobile device",
      "secret": false
    }
  ],
  "message": {
    "status": "PENDING",
    "percent_complete": 40,
    "auth_percent_complete": 80,
    "job_timeout": 827027,
    "status_message": "Please acknowledge the link sent to your email or phone.",
  }
}
{
  "type": "initial_account_link",
  "job_id": 101,
  "envelope_id": “<GUID>”,
  "account_link": [
    {
      "key_name": "username",
      "label": "Username",
      "secret": false
    },
    {
      "key_name": "password",
      "label": "Password",
      "secret": true
    }
  ],
  "message": {
    "status": "PENGING_NEWCREDS",
    "percent_complete": 45,
    "auth_percent_complete": 90,
    "job_timeout": 827027,
    "status_message": "The credentials provided were incorrect.",
  }
}
{
  "type": "security",
  "job_id": 101,
  "envelope_id": “<GUID>”,
  "account_link": [
    {
      "key_name": "security_1",
      "label": "What is your mother's maiden name?",
      "secret": true
    }
  ],
  "message": {
    "status": "PENGING",
    "percent_complete": 45,
    "auth_percent_complete": 90,
    "job_timeout": 827027,
    "status_message": "The site is requiring additional information.",
  }
}

To reduce the amount of time required to complete the job, starting a job before credentials have been collected can reduce the overall user waiting time. When this occurs, there will be a credential_request and a corresponding envelope_id that will need to be used to respond with the initial credentials. Note that all messages with a status that starts with "PENDING" indicate that the message will be accompanied with an account_link parameter, and that data is required from the user and the job will block until responded to.

Credential Responses

The most common way to respond to a message request, is through request hydration and the jobs endpoint. By simply providing a header that contains the appropriate envelope_id ("x-cardsavr-envelope-id": "<GUID>"), responses become simple account updates. Note that credential responses aren't always username/password (although that's most common). The merchant site endpoint defines the necessary values for each merchant site. (e.g. "pin" or "email")

Endpoint: PUT /place_card_on_single_site_jobs/:job_id

{
  "account": { 
    "account_link" : {
      "username": "my_username@foo.com",
      "password": "my_password"
    }   
  }
}

or for TFA responses:

{
  "account": {    
    "account_link" : {
      "tfa": "123"
    }
  }
}

or for TFA messages - these should be respoonded to immediately with "ack", the job will simply block until the ack sent to their phone is replid to.

{
  "account": {    
    "account_link" : {
      "tfa": "ack"
    }
  }
}

or for security questions:

{
  "account": {    
    "account_link" : {
      "security_1": "Max",
      "security_2": "Smith"
    }
  }
}

The other mechanism is to post directly to the messaging endpoint for tfa responses:

Endpoint: POST /messages/place_card_on_single_site_jobs/job_id:/credential_responses

{
  "job_id": 101,
  "envelope_id": "<ENVELOPE_ID>",
  "account_link" : {
    "tfa": "123"
  }
}

This method is not recommended since this can all be accmplished using the account and job endpoints.

All the SDKs provide simple interfaces for ensuring the correct data is returned in the response. There are also sample tests that walk through how to attach envelope_ids in responses.

Querying Messages by Cardholder

Since it is commmon for multile jobs to be running simultaneously, it is oftentimes easiest to query multiple job messages at once. Since every job message is accompanied by its id, it's a relatively simple exercise to route the messages to the right component that manages each job.

Endpoint: GET /messages/cardholders/:cardholder_id

Querying Messages by Job

It is also possible to only query against a single job. As with cardholder message queries, the credential requests remain as messages until a response is sent.

Endpoint GET /messages/place_card_on_single_site_jobs/:job_id

Broadcast Messages

The broadcast message endpoints are actually available for direct consumption as well. These messages can be used to set up monitoring services, or applications that can receive messages across multiple channels. As most implementation do not require such complexity, there is limited SDK support.

Endpoint: GET /messages/place_card_on_single_site_jobs/:job_id/broadcasts

In order to receive broadcast messaages, you must first register and set up a dedicated channel.

Endpoint: GET /messages/place_card_on_single_site_jobs/:job_id/broadcasts/registrations

This endpoint returns an access key that needs to be included with status queries. You must include the cardsavr-messaging-access-key header as part of the request, also avaialble as a parameter in the SDK.

Request messages adhere to a slightly different format.

Endpoint: GET /messages/place_card_on_single_site_jobs/:job_id/credential_requests

Messaging Architecture

Here is a diagram of how multiple channels can be used to monitor job status. Note that credential requests will not work across multiple channels, only status messages.

Messaging Architecture

Previous
Job Progress