Callbacks

The most important parts of Spectre API (e.g. Login management) are asynchronous. Applications can poll Spectre API in order to retrieve the updated information.

Every Web application has to provide a set of valid URLs which we will use to notify about the fetching progress. Other applications can poll Spectre API in order to retrieve the updated information.

There are several common points about the request we send to the callback URLs provided by the client:

  • The Content-Type header is application/json;
  • There is a Signature header that identifies the request was signed by Spectre API;
  • The request method is always POST;
  • The JSON object sent will always have a data field;
  • The meta field will display the version of the callbacks API.

You can set the callback URLs for your application by accessing your callbacks page.

Due to security reasons, the callbacks can be sent to ports 80/HTTP (in test and pending modes) and 443/HTTPS (in test, pending and live modes) only!

Signature

In order the client to identify that the request is coming from Spectre API, there is a Signature header in the request.

Signature - base64 encoded SHA1 signature of the string represented in the form callback_url|post_body - 2 parameters concatenated with a vertical bar |, signed with the Spectre API’s private key, which corresponds to the following public key:

  -----BEGIN PUBLIC KEY-----
  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq/191bAXPj7Rm+rmmjF4
  RzX3Xrtj/tUg+h3Yik1MnFQWkmrwRiW0mnUqSWbbcPdQL/s3XReyyaaxePbSfLep
  KOMx/HllnimwgJFqA2Tqix+Yxobab7bV8K/QoM2fkH57i38IfL7MZX5bInqczysN
  u2NQ6cydxAe7zolfMgtHkN4cUVYOsNm7tWK0OJgM+VHYvzNDFnbrkLRcf5LD2jh2
  4E9rSvQfpqckabz2F3TYu1v5Ybf2RXIxehW0zEEMGvLZMOvO9fYW+H8GHjj9GyRJ
  pSw2GjKx51YN3FsN45YI/ElnEitjgCZmq8CuZvUItXooKqNsfAp0smChBC2YIJ1n
  4wIDAQAB
  -----END PUBLIC KEY-----

An example of the string that is to be used to generate the signature looks as follows:

https://www.client.com/api/callbacks/success|{"data":{"login_id":1234,"customer_id":4321,"custom_fields":{}},"meta":{"version":"3","time":"2017-01-03T13:00:28Z"}}

The pseudocode that we use to generate the signature looks like this:

base64(sha1_signature(private_key, "callback_url|post_body")))

Requests cycle

To avoid unnecessary requests, performance issues and fetching all data, use the following diagramm:

Success

We send a callback to your application’s success URL whenever any manually triggered operation has caused a change in the data we store for a particular login.

For instance, after you’ve redirected your user to the Connect page and they have selected their provider, filled in the credentials and pressed Connect, we’ll send you a success callback. This callback will contain the customer identifier and the ID of the newly created login. Afterwards, your application will be able to use the show login route and query the information about this login. You could also fetch the login’s accounts and query the accounts (if any exist at the moment we sent the callback).

Whenever we have more information about the login, we will send another success callback.

A success callback marks a change in the data and you can generally expect from one to three success callbacks with the same payload within several minutes. We recommend that your application fetch the full login data, along with the accounts and transactions at each callback, as some information might change during the fetching process.

For instance, when your user has created a login using Salt Edge Connect, we will send the following success callback:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445,
    "custom_fields": { "key": "value" }
  },
  "meta": {
    "version": "3",
    "time": "2017-07-18T08:58:52Z"
  }
}

You can now use the show login route and obtain the provider, country and some other attributes of the new login.

Failure

Sometimes we fail to fetch the information from the provider’s page. It might happen because the interactive data was not sent by the user, the credentials are wrong or we could not perform one of the steps of the fetching process. In this case, you will receive a fail callback, containing a JSON similar to the following:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445,
    "custom_fields": { "key": "value" },
    "error_class": "InvalidCredentials",
    "error_message": "Invalid credentials."
  },
  "meta": {
    "version": "3",
    "time": "2017-07-18T08:58:52Z"
  }
}

After you get this callback, you need to request the login to check for its updates. Please note that even if there’s an error, we still store the login.

If you would like to delete the erroneous login, you can use the remove login route. In case of an InvalidCredentials error, we recommend you to use a Reconnect.

In order to avoid login duplication errors, when you request the login after a fail callback, we recommend you remove the login in case the login’s last_fail_error_class is InvalidCredentials and the login has no accounts.

Additional callbacks

There are three additional callbacks that your app needs to implement in order to use the API-only version of Spectre.

Notify

Since you issue a create request to create a Login, Salt Edge can inform you about the progress the new login is going through using a Notify callback.

Your app can expect the notify callback several times, depending on the type of the login, but you can use this information to inform your user about what’s happening with their connection.

The possible stages sent in a notify callback are as follows:

  • start - the fetching process has just begun;
  • connect - connecting to the data source;
  • interactive - waiting for the interactive credentials;
  • fetch_holder_info - fetching the information about account holder;
  • fetch_accounts - fetching the accounts;
  • fetch_recent - fetching the data for a recent period (several months);
  • fetch_full - fetching the data for a longer period;
  • disconnect - disconnecting from the data source;
  • finish - wrapping up the fetching process.

Note that for some of the logins, you might not receive all the stages.

Here’s an example callback sent to the /notify route of your app:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445,
    "custom_fields": { "key": "value" },
    "stage": "start"
  },
  "meta": {
    "version": "3",
    "time": "2017-07-17T08:58:52Z"
  }
}

Interactive

Some of the providers require an additional step before signing in, asking users to input an SMS, Token, solve a CAPTCHA, etc.

Whenever we encounter that the login requires an interactive step, we will send the interactive callback to the interactive route set in your app’s profile. Your app should prompt the user for the interactive credentials and send them to the interactive route.

We also send a snippet of HTML so that it would be easier for your app to display the CAPTCHA or image to the user. If the provider requires filling a CAPTCHA, the img tag in the HTML will contain the image URL.

During this process, the login’s stage will be set to interactive.

The interactive callback should contain the values of the interactive_credentials field from the corresponding provider.

Here’s an example callback sent to your app’s /interactive route:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445,
    "custom_fields": { "key": "value" },
    "stage": "interactive",
    "html": "<div id='interactive'><img src='https://docs.saltedge.com/images/saltedge_captcha.png' width='10' height='10' alt='some description' title='some description'></div>",
    "session_expires_at": "2017-07-17T09:58:52Z",
    "interactive_fields_names": ["image"]
  },
  "meta": {
    "version": "3",
    "time": "2017-07-17T08:58:52Z"
  }
}

Destroy

Whenever a login gets removed, we will send a callback to your application’s destroy URL, if such exists.

Here’s an example callback sent to your app’s /destroy route:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445
  },
  "meta": {
    "version": "3",
    "time": "2013-05-17T14:29:35Z"
  }
}

Service

Whenever the login had issues in the past and a change was made in login’s provider codebase, your application will receive a callback telling that a refresh is needed in order to update login’s data.

The possible reasons sent in a service callback are as follows:

  • fixed - a fix was made;
  • updated - an update was made;

Here’s an example callback sent to the /service route of your app:

{
  "data": {
    "login_id": 123,
    "customer_id": 34445,
    "custom_fields": { "key": "value" },
    "reason": "updated"
  },
  "meta": {
    "version": "3",
    "time": "2017-07-17T08:58:52Z"
  }
}