Callbacks

Schibsted account supports server-side callbacks that enable your service to subscribe to changes in data. Your service can then cache data and receive updates, rather than continuously poll Schibsted account's servers. Caching data and using this API can improve the reliability of your app or service and decrease its load times.

Whenever a subscribed change occurs, Schibsted account makes an HTTP POST request to a callback URL of your choice, with a list of changes. Your app will generally receive notification of the change within a couple of minutes of its occurrence.

Please ensure that your callback endpoints are accessible by Schibsted account through your firewalls and that errors generated by the your callback endpoint are monitored and handled.

Types of callbacks

Schibsted account currently supports two kinds of callbacks:

  • User status changes

Callback requests

When an object changes, an HTTP POST request will be made to the client-defined callback URL. The response body will contain Base64 URL encoded text signed with your signature secret.

Note: The content-type of the POST request made by Schibsted account is "text/plain".

NOTE: Your signature secret is not the same as your client secret (which is used for authentication). It is a different secret specifically used for signing requests and decoding signed responses. If you do not have a signing secret, contact Schibsted account.

The response body contains an encoded signature and encoded data, separated by a dot, e.g. "<signature>.<data>". Here is an example:

GTUVPjN1LzdyU1qwHjnMKS2oNx.eyJvYmplY3QiOiJvcmRlciIsImVudHJ5IjpbeyJvcmRlcl9pZCI6IjMwMDAxNCIsI

The decoded data is a JSON object:

{
  "object": "user",
  "algorithm": "HMAC-SHA256",
  "entry": [
      {
          "userId": 123,
          "changedFields": "status",
          "time": "2012-10-19 10:10:15"
      },
      {
          "userId": 456,
          "changedFields": "status",
          "time": "2012-10-19 10:10:19"
      }
   ]
}

Decoding responses

PHP

The following example manually parses and verifies the signature of the request:

<?php
function parse_signed_request($signed_request, $secret) {
  list($encoded_sig, $payload) = explode('.', $signed_request, 2);
  $sig = base64_url_decode($encoded_sig);
  $data = base64_url_decode($payload);
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if (!hash_equals($sig, $expected_sig)) {
    return null;
  }
  return $data;
};

function base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

$payload = file_get_contents("php://input");
$parsed = parse_signed_request($payload, $client_sign_secret);
$data = json_decode($parsed, true);

Java

The following example manually parses and verifies the signature of the request:

byte[] signature = base64UrlDecode(request.split("\\.")[0]);
byte[] payload = base64UrlDecode(request.split("\\.")[1]);
byte[] expectedSignature = null;

try {
    SecretKeySpec sks = new SecretKeySpec(signSecret.getBytes("UTF-8"), "HmacSHA256");
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(sks);
    expectedSignature = mac.doFinal(payload.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException ex) {
    throw ex;
}

if (!MessageDigest.isEqual(expectedSignature, signature)) {
    throw new SpidApiException("Signature is not valid!");
}

Processing callback data

The response only contains a description of what changes occurred - it does not inline individual resources. Having received, decoded and verified the integrity of callback data, the client should iterate through all the entry objects and retrieve up-to-date objects through relevant endpoints. These objects can be safely cached until the next callback request is made.

Schibsted account aggregates changes and sends batched updates every five minutes. This means that for every subscription, you will receive at most one request every five minutes, and possible less often (if there are fewer changes).

Callback responses

When your client receives callback requests, it should respond with HTTP code 202 Accepted. If the callback does not respond with 202, Schibsted account will retry again immediately, and then four more times at increasing intervals over the subsequent 25 hours. If all of these requests go un-accepted, the callback request will be marked as failed.

Retries occur after five minutes, fifteen minutes, one hour, twelve hours and again twelve hours. There is a thirty second timeout before Schibsted account quits the connection and considers the request failed. Do not synchronously process callback data before responding to the callback request.

User status callback

This callback will inform the client when a user's status changes.

User status state machine

Table of Contents

Relevant type definitions

Help us improve

Did you spot an error? Or maybe you just have a suggestion for how we can improve? Leave a comment, or better yet, send us a pull request on GitHub to fix it (in-browser editing, only takes a moment).

History of this page

Comments/feedback

Do you have questions, or just want to contribute some newly gained insight? Want to share an example? Please leave a comment. SPiD reads and responds to every question. Additionally, your experience can help others using SPiD, and it can help us continuously improve our documentation.