Hello World tutorial

Overview

Getting started

Before you’ll be taking your first steps developing a Speakap Application, let’s familiarize ourselves with some key concepts:

Speakap Network
After completing the Speakap registration, you have access to your own secure and protected enterprise social network, accessible via web through a unique subdomain or using one of our mobile applications. When we talk about Speakap we most often refer to the software platform — and sometimes the company itself — and when talking about a Speakap Network we mean it in the context of the social network of a single organization.
Speakap Market
Speakap Network administrators are able to install publicly available or inhouse-developed applications. This feature is known as the App Market or Speakap Market. It is accessible via the network settings menu. Please note the difference between installed and available apps. You can add applications to the Market, making them publicly available or only for your network. But to actually use them you need to install them afterwards.
Speakap API
This is our RESTful API. All of the data your app might need, you will need to retrieve from here.
EID
Every resource available from the Speakap API has a unique identifier. With one or two exceptions, all of them are hexadecimal representations of a 64-bit integer. We dubbed them External Identifiers or EIDs, because they are identifiers shared with the rest of the world.
Speakap Client
Speakap Clients are the official web and mobile clients developed by Speakap. To refer to a specific Speakap Client we most likely will include the target device: Speakap Desktop Client, Speakap iOS Client, Speakap Android Client etc. The Speakap Desktop Client is sometimes also referred to as Speakap Frontend.
OAuth 2.0
The Speakap API secures its data by limiting access to authorized clients only. OAuth 2.0 is a framework that standardizes both authentication and authorization.
Access Token
Although we claim our API is stateless, this isn’t entirely true. The access token is a string representing the client’s credentials. The Speakap API uses the access token to verify on behalf of what end user requests are being made. Because the API has to temporarily store this token, we actually created a state.
Refresh Token
Access Tokens are very short lived and are transmitted every single request. The refresh token is a similar string used to obtain new access tokens. Refresh tokens are valid for much longer as they are used only sporadically and never sent to the API.
Speakap Authenticator
The Authenticator deals with authentication requests and issuing access and refresh tokens.
SSO
When we talk about Single Sign On, unless stated otherwise, we mean: Using Speakap to login to third-party software.
Signed Request
When a request is signed, client’s are able to verify the origins of the request. A signed request contains a signature and should only be trusted if the receiving client is able to generate an identical signature, based upon pre-arranged agreements.
Manifest
This is essentially the configuration of your Speakap Application. It’s a JSON-file containing meta-data needed to run your app as intended.
Entry
Application Entries are entry or access points to your app. They describe what part of the application is initially loaded and where in the UI it is visible.
JavaScript API
This is our client-side API designed to help you build your application’s front-end. It’s a javascript library that acts as a proxy between the Speakap Frontend and the Speakap API. Among other things it facilitates making XHR request to the API on behalf of the logged-in user.

Now that that’s off of our chests, let’s digg in...

Application manifest

Assuming that you already have a Speakap Network at your disposal; let’s start writing a manifest. The most simple manifest contains the application’s name in just one language:

{ "name": { "en-US": "Hello World", "permissions": [], "entries": [] } }

The two empty arrays permissions and entries are there to satisfy our manifest validator. They will be discussed later on in this tutorial.

It’s speaks for itself that this can be extended with many more languages or translations:

{
    "name": {
        "en-US": "Hello World",
        "nl-NL": "Hallo Wereld",
        "de-DE": "Hallo Welt",
        "fr-FR": "Bonjour Monde"
    },
    "permissions": [],
    "entries": []
}

When your app is listed in the Speakap Market the name is preceded with an icon image. The icon can be any publicly available web image (preferably PNG or GIF).

{
    "name": {
        "en-US": "Hello World"
    },
    "permissions": [],
    "icon": "http://developer.speakap.io/world-icon.png",
    "entries": []
}

Entries

To make the application available from Speakap we need to create an entry. The most common entry points are:

  • main Large iframe that opens after clicking the app icon from the main navigation.
  • network-timeline-widget Widget on the right-hand side of the network timeline.

Let’s add both these positions:

{
    "name": {
        "en-US": "Hello World"
    },
    "permissions": [],
    "icon": "http://developer.speakap.io/world-icon.png",
    "entries": [
        {
            "position": "main",
            "responsive": false,
            "devices": "all",
            "icon": "\uf0ac",
            "label": {
                "en-US": "Hello World"
            }
        },
        {
            "position": "network-timeline-widget",
            "devices": "all",
            "label": {
                "en-US": "Hello World"
            }
        }
    ]
}

The icon we use in the main navigation is one of the Font Awesome icons. By default a limited set of these icons is available within Speakap. Contact our Support department to request an additional icon.

The observant reader may have noticed the devices property. This allows you to have your entry target specific devices, one of: desktop, phone, tablet or all.

One important property is still missing from the entries, namely the actual URL to your application. We’ll save that for a bit later.

Your application

Security

As you can imagine, one of the most important things to consider is security. But first let’s distinguish two areas of Speakap Applications:

client-side:The client-side is the front-end of your application, i.e., everything that operates within a browser’s context. This part of an app must use the JavaScript API to communicate with both the Speakap Client and Speakap API.
server-side:From your servers you are able to do requests directly to the Speakap API, i.e. back-end requests. Because no client is involved you are allowed to use a special App Access Token to authorize these requests.

The above makes clear that you have two options to communicate with our API: client-to-server and server-to-server. The first restricts you to the authorization level, i.e. privileges, of the logged-in user as it compels you to do all requests on its behalf. Not only that, but you are also bound by the endpoints whitelisted by us. The second offers no restrictions on specific resources, but you are, however, limited to permissions we make available for apps.

In most cases you wil probably use a combination of the two and in case of a single-page application you might even write your own API or web service capable of delivering data to your front-end.

Now let’s start coding our Hello World app:

<html>
    <head>
        <title>Hello World</title>
    </head>

    <body>
        <p>Hello Speakap user!</p>
    </body>
</html>

If you would upload a file like this to a public-facing web folder you just finished your first, kinda useless, Speakap Application.

But wait...

We still need to finalize the manifest with the correct URL and complete the upload and install process. Assuming you picked the filename helloworld.html the manifest will now read:

{
    "name": {
        "en-US": "Hello World"
    },
    "icon": "http://developer.speakap.io/world-icon.png",
    "entries": [
        {
            "position": "main",
            "responsive": false,
            "devices": "all",
            "url": "https://yourdomain.com/app/folder/helloworld.html",
            "icon": "\uf0ac",
            "label": {
                "en-US": "Hello World"
            }
        },
        {
            "position": "network-timeline-widget",
            "url": "https://yourdomain.com/app/folder/helloworld.html",
            "devices": "all",
            "label": {
                "en-US": "Hello World"
            }
        }
    ]
}

Upload & Install

Upload your manifest to the same location as the app, so that it becomes publicly accessible as well. Then go to the Speakap Market of your Speakap Network and click the “+ Application” button. This opens the list of available apps. Next click “Add application to market” and you will be presented with an input field. Fill in the URL to the manifest and press “Install”.

Once successfully added, your application will be the first entry in the list containing an App ID and Secret. We recommend creating a screenshot or at least writing down both these values, especially the secret.

Combine these two values and you’ve got your application’s Access Token:

[App ID]_[Secret]

The app is only available from the App Market of your Speakap Network and nowhere else. To install click anywhere on or around the app’s name or to uninstall simply click the trash can. The app can be deleted by clicking the trash can from the available apps list. The whole flow of add-install-uninstall-delete can be repeated as often as needed. Contact Speakap if you would like your application to be published to the public App Market.

Now that we have our App ID we can start using the Speakap API. Let’s update the HTML-file and add some scripts.

<html>
    <head>
        <title>Hello World</title>
        <script type="text/javascript">
            var Speakap = { appId: "...", signedRequest: "..." };
        </script>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript" src="js/speakap.js"></script>
    </head>

    <body>
        <p>Hello Speakap user!</p>
    </body>
</html>

It’s easy to see where the App ID needs to be filled in. The two JavaScript files are part of our SDK and can be downloaded from Github.

The next hurdle we need to clear is the second property of the Speakap initialization object.

Signed Request

As explained earlier on; a signed request lets you verify that a request actually originated from where you expect it to be originated from. The Speakap Frontend opens an app by sending a POST request to the relevant URL from its manifest. This request is signed using the App Secret which, if kept confidential, is only known to the Speakap API and the Speakap Application.

It’s the app’s responsibility to asses the validity of the request by comparing the signature from the request to one generated on the fly in an identical way. Our SDK provides implementations in various languages to take care of this.

In the next example we will use the PHP SDK to check the signature:

<?php

// Assume auto-load is in place for the Speakap\SDK namespace

use Speakap\SDK as SpeakapSDK;

$signedRequest = new SpeakapSDK\SignedRequest('/* App ID */', '/* Secret */');

if (!$validator->validateSignature($_POST)) {
    die('Invalid signature');
}

$encSignedReq = $signedRequest->getSignedRequest($_POST);

echo <<<HTML
<html>
    <head>
        <title>Hello World</title>
        <script type="text/javascript">
            var Speakap = { appId: "/* App ID */", signedRequest: "$encSignedReq" };
        </script>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript" src="js/speakap.js"></script>
    </head>

    <body>
        <p>Hello Speakap user!</p>
    </body>
</html>
HTML;

Handshake

With both the correct App ID and Secret in place we were able to bootstrap the JavaScript API with a validated signed request. Subsequently this will trigger a handshake with the Speakap Frontend. Completion of the handshake will lead to the fulfillment of a Promise. This promise acts as the entry point of our code.

We can now personalize our greeting with the full name of the logged in user:

<!-- Rest of page is ommited to save space -->

<body>
    <script type="text/javascript">
        /* Assume sanitize() is a custom function stripping malicious content */
        Speakap.doHandshake.then(function() {
            Speakap.getLoggedInUser().then(function(user) {
                document.write('<p>Hello ' + sanitize(user.fullName) + '!</p>');
            });
        });
    </script>
</body>

Using the locale parameter from the signed request you can imagine how the above example can be adapted to support multiple languages.

To demonstrate doing XHR API requests we could also grab the full name from the user resource after retrieving it from the server. The JavaScript part would then read:

/* Assume sanitize() is a custom function stripping malicious content */

Speakap.doHandshake.then(function() {
    Speakap.getLoggedInUser().then(function(loggedInUser) {
        Speakap.ajax('/users/' + loggedInUser.EID + '/').done(function(user) {
            document.write('<p>Hello ' + sanitize(user.fullName) + '!</p>');
        });
    });
});

Server-side

If front-end technologies aren’t your strongest point, the same result can be achieved from the server. As you saw earlier the validation of the signed request is done server-side, so we have access to the EID of the logged-in user there as well.

Using the access token of our Hello World App we will perform a cURL request:

<?php

/*
 * Assume signed request has been properly validated and malicious content
 * will be stripped from the output using a custom sanitize() function
 */

$signedParams = $signedRequest->getSignedParameters($_POST);

$baseUrl = 'https://api.speakap.io/networks/' . $signedParams['networkEID'];

$accessToken = /* App ID */ '_' /* Secret */;

$ch = curl_init("$baseUrl/users/{$signedParams['userEID']}/");

curl_setopt_array($ch, array(
    CURLOPT_HEADER => false,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => array(
        'Accept: application/vnd.speakap.api-v1.4+json',
        'Authorization: Bearer ' . $accessToken
    )
));

$response = curl_exec($ch);
curl_close($ch);

$user = json_decode($response);

echo "<p>Hello " . htmlspecialchars($user->fullName) . "!</p>";

Or if you are more comfortable using a tool like Guzzle:

<?php

$signedParams = $signedRequest->getSignedParameters($_POST);

$client = new GuzzleHttp\Client(array(
    'base_uri' => 'https://api.speakap.io/networks/' . $signedParams['networkEID']
));

$accessToken = /* App ID */ '_' /* Secret */;

$response = $client->get("/users/{$signedParams['userEID']}/", array(
    'headers' => [
        'Accept' => 'application/vnd.speakap.api-v1.4+json',
        'Authorization' => 'Bearer '. $accessToken
    ]
));

$user = json_decode($response->getBody());

echo "<p>Hello " . htmlspecialchars($user->fullName) . "!</p>";

There you have it! A server-to-server request resulting in a 403-response. Wait, what?!

Authorization

One important aspect we already touched upon, but did not yet cover: permissions. All our endpoints and resources are protected against unauthorized and unprivileged usage, so you need to include the required permissions in your manifest. For publicly available apps these permissions will be screened by us during an audit we’ll do before publication.

The final manifest will look like this:

{
    "name": {
        "en-US": "Hello World"
    },
    "icon": "http://developer.speakap.io/world-icon.png",
    "permissions": [
        "get_profiles"
    ],
    "entries": [
        {
            "position": "main",
            "devices": "all",
            "url": "https://yourdomain.com/app/folder/helloworld.php",
            "icon": "\uf0ac",
            "label": {
                "en-US": "Hello World"
            }
        },
        {
            "position": "network-timeline-widget",
            "url": "https://yourdomain.com/app/folder/helloworld.php",
            "devices": "all",
            "label": {
                "en-US": "Hello World"
            }
        }
    ]
}

Further reading

One last flow this tutorial doesn’t cover uses the OAuth 2.0 Authorization Code Grant. In this redirection-based flow your app asks the end user explicit permission to do certain requests and retrieve specific data. It is then able to obtain a special access token from the Authenticator scoped to what was allowed earlier by the user.

Single Sign On tutorial