Introduction to OAuth

The first step to begin using the API is to register your application with our API service. When registering your application, you will be asked to select one or more audience segments to associate with it. Every application must be associated with at least one audience segment, and applications are self-contained in that they only have access to members of the audience segments in which they are associated. If you do not specify any audience segments when registering your app, an empty one will be created for you.

From the OAuth process, your application is given a temporary access token which can be used to set and retrieve data, authenticated as the end-user. Whenever you need to access the DaniWeb Connect API, you must send a valid, non-expired access token along with your request. Currently, access tokens have a lifespan of 24 hours.

For a summary of the functionality of the API before getting started, please read the technical overview.

Serverside Apps

The OAuth explicit flow is used for web-based applications developed in serverside programming languages such as PHP, Python, Ruby or C#. With explicit flow, the third-party application redirects its end-user to DaniWeb Connect's OAuth URL for authorization. Successful completition of this process will result in the end-user being redirected back to your application's website, along with a unique code. This one-time-use code can be exchanged by your application for a temporary access token, which can be used to connect to the DaniWeb Connect API. The entire process begins by sending your application's end-user to https://www.daniweb.com/connect/oauth/auth with the following query string (GET) parameters:

  • response_type (Required): code
  • redirect_uri (Required): URL within your application where you want our service to redirect the end-user to upon authorization
  • client_id (Required): Your application's Client ID #
  • state (Optional): Unique anti-CSRF string
  • scope (Optional): Comma-delimited list of permissions that you want to request from the end-user

From the DaniWeb Connect OAuth page, if the end-user is not currently logged into DaniWeb, they are prompted to either log in or join. Otherwise, this step is bypassed. The end-user is then prompted to authorize your application to access their account. If they have previously authorized your application, the entire authorization process is transparent and they are immediately redirected back to your application. Otherwise, once they authorize, then they are redirected back at that time.

Upon authorizing that your application can access their account, the end-user will be redirected to your application with the optional state as a query string parameter, and a code will also be passed along as an additional query string parameter. The code can be retrieved from the query string and exchanged for an access token via a POST request.

Here is a link to begin the OAuth process with our own demo app:

https://www.daniweb.com/connect/oauth/auth?response_type=code&client_id=1&scope=profile_read&redirect_uri=https://www.daniweb.com/connect/oauth/demo

Notice that this link includes query parameters specifying the response_type, redirect_uri, client_id, and scope. As specified above, state and scope are optional.

Native Apps

The serverside implementation redirects the end-user to DaniWeb Connect's authorization page, and, upon the end-user's acceptance, the authorization page then sends the user back to your application along with a code as a query string parameter. However, desktop applications don't easily have the ability to accept incoming HTTP requests. Therefore, while they would be able to redirect the end-user to the service's authorization page, without the complexity of running a local web server, they have no means of listening for and accepting the service's request for the application which includes the code. The out-of-band implementation, or OOB, allows desktop applications that don't have the ability to accept incoming HTTP requests to still acquire an access token and make authenticated API calls.

To implement OOB flow from within your desktop or mobile application, launch a web browser and direct the end-user to https://www.daniweb.com/connect/oauth/auth with the following query string (GET) parameters:

  • response_type (Required): code
  • redirect_uri (Required): urn:ietf:wg:oauth:2.0:oob or urn:ietf:wg:oauth:2.0:oob:auto
  • client_id (Required): Your application's Client ID #
  • scope (Optional): Comma-delimited list of permissions that you want to request from the end-user

The end-user will be asked to authorize your application just as with serverside flow. Upon acceptance, they will be redirected to a web page that will have the authorization code in the browser window titlebar. If you launched the web page within an embedded web browser within your application, you can retrieve the code from the titlebar and immediately close the browser without prompting the end-user. If this is the case, you will want to specify a redirect_uri of urn:ietf:wg:oauth:2.0:oob:auto. Just in case your application is unable to close the browser window, the end-user will be politely prompted to please close the window. Here is a link to our demo using this method:

https://www.daniweb.com/connect/oauth/auth?response_type=code&client_id=1&scope=profile_read&redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto

However, if your application is unable to retrieve the code from the browser's titlebar, you will want to use a redirect_uri of urn:ietf:wg:oauth:2.0:oob. The end-user will be politely asked to copy/paste it into your application if prompted. Your application can offer a form where the end-user can paste in the authorization code upon seeing the prompt to do so. Here is a link to our demo using this method:

https://www.daniweb.com/connect/oauth/auth?response_type=code&client_id=1&scope=profile_read&redirect_uri=urn:ietf:wg:oauth:2.0:oob

The code acquired can be exchanged for an access token via a POST request.

Access Tokens

Upon completing a serverside OAuth flow, the end-user is redirected back to your application. The string of code retrieved from an explicit OAuth request can be exchanged for an access token. You can do so by making a POST request to exchange the code and your application's credentials (client_id and client_secret) for a temporary access token. The following POST parameters are required for the https://www.daniweb.com/connect/oauth/access_token request:

  • code (Required): code that is returned from the end-user authorization process
  • redirect_uri (Required): Same redirect_uri as used to acquire the code
  • client_id (Required): Your application's Client ID
  • client_secret (Required): Your application's secret
  • grant_type (Required): authorization_code

A call to retrieve the access token results in being sent back a JSON object which includes the property access_token as well as a couple of other properties. expires_in will always be set to 86400, which means that our access tokens always have a lifespan of 86,400 seconds, or 24 hours. expires will be a UNIX timestamp representation of 24-hours from now. The refresh_token property should be stored in a safe place, because you will need it in order to refresh the access token once it has expired.

The following PHP code illustrates the process in which a code is exchanged for an access token. Once a valid access token is retrieved, a request is made to the API to fetch and display information about the end-user.

// Store some stuff we will need into variables
$client_id = 'Your application's Client ID';
$client_secret = 'Your application's Client Secret';
$current_url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

// Initiate a cURL POST request to exchange the ?code= that was passed in as a GET parameter for an access token
$ch = curl_init('https://www.daniweb.com/connect/oauth/access_token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
	'code' => $_REQUEST['code'],
	'redirect_uri' => $current_url,
	'client_id' => $client_id,
	'client_secret' => $client_secret,
	'grant_type' => 'authorization_code'
));

// Retrieve the JSON response from the cURL request, and decode it into a PHP object
$response = json_decode(curl_exec($ch));

// Close the cURL request
curl_close($ch);

// Retrieve the access token from the PHP object
$access_token = $response->access_token;

// Initiate a GET request to fetch information about the end-user by passing in our newly acquired access token, and then decode that JSON response
$output = json_decode(file_get_contents("https://www.daniweb.com/connect/api/users/~?access_token=" . urlencode($access_token)));

// Print a message to the end user
echo 'Hi, '.$output->data->profile->first_name.'!';

In most cases, you will have a web-based application that accesses the end-user's account within a timely manner after they have authorized you access to it. However, in some situations, once you have been granted authorization, you will want to perpetually access the end-user's account on their behalf behind the scenes, such as via a cron job or scheduled task. In such a case, your application will be accessing the DaniWeb Connect API using the end-users' access tokens at a time when the end-users are not themselves in front of their web browsers. Just as we issued a request to https://www.daniweb.com/connect/oauth/auth above, to gain an access token, we'll do something similar to refresh it, albeit with slightly different POST parameters:

  • refresh_token (Required): refresh_token that is a part of the above JSON object
  • client_id (Required): Your application's Client ID
  • client_secret (Required): Your application's secret
  • grant_type (Required): refresh_token

JavaScript (Clientside) Apps

The implicit flow allows you to acquire an access token and access the API entirely from within a browser-based javascript application. Because the entire application is browser-based and client-facing, we do not use the client_secret because the end-user would have access to it by viewing the javascript source code from their web browser. Instead, the application authenticates itself by ensuring that it resides on the same domain name as you used when you registered your application.

Begin by redirecting the end user to https://www.daniweb.com/connect/oauth/access_token, requesting a response of a token as opposed to code as we do with a serverside implementation. When working with a serverside implementation, the authorization process returns us a code which we can then use to exchange for an access token. When working with a clientside implementation, however, we are immediately granted an access token as a result of the authorization process. This is what the initial OAuth request looks like:

  • response_type (Required): token
  • redirect_uri (Required): URL within your application where you want our service to redirect the end-user to upon authorization
  • client_id (Required): Your application's Client ID #
  • scope (Optional): Comma-delimited list of permissions that you want to request from the end-user

Upon successful authorization, the end-user will be redirected to your redirect URI with a hash which contains the access token. It will look something like this: example.com#access_token=abc&expires_in=86400. Javascript can be used to fetch the hash of the currently opened web page. Once the entire hash is in a string variable, it can be manipulated to extract the access token. Here is an example of the implicit OAuth flow:

https://www.daniweb.com/connect/oauth/auth?response_type=token&client_id=1&scope=profile_read&redirect_uri=https://www.daniweb.com/connect/oauth/demo/javascript

The following JavaScript uses jQuery to retrieve an access token from a URI hash. Just like in the PHP example above, once a valid access token is retrieved, a request is made to the API to fetch and display information about the end-user.

// Retrieve the URI hash
var string = window.location.hash.substr(1);

// Split the hash into an array separated by &
// So we will have arr[0] => 'expires_in=86400' arr[1] => 'access_token=abc'
var query = string.split('&');
var param;

// Loop through each item in the array
for (var i = 0; i < query.length; i++)
{
    // Split each item into an array separated by =
    // So we will have arr[0] => 'access_token' arr[1] => 'abc'
    param = query[i].split('=');
    
    // If we are looking at an access token, store it and break out of the loop
    if (param[0] == 'access_token')
    {
        access_token = param[1];
        break;
    }
}

// Use our newly generated access token to acquire information about the end user
$.getJSON('https://www.daniweb.com/connect/api/users/~?access_token=' + access_token + '&callback=?', function(response) {
    // Print a nice message to the end user
    $('body').append('Hi, ' + response.data.profile.first_name + '!');
});

API Endpoints

The core of our API are our endpoints which return either JSON or JSONP. JSON is a format that lends itself well to transmitting data objects between services and web applications. Your application would issue an HTTP request to our API, and the results will be returned in JSON format. JSON is a very portable, language-agnostic format and tools for parsing it are readily available for most modern programming languages. We try our best to ensure RESTful JSON objects, which essentially just means that we try to adhere to REST standards and principles. This makes it quick to pick up our API and begin doing some advanced things right away if you have previous REST API experience.

All endpoints return data sorted alphabetically by property name. It is important to note that the sample responses provided in our API reference include all possible data that may be returned. Properties that are empty or null are always ommitted. Insufficient user permissions may also result in not all available properties being returned. It should never be assumed that a property exists in a response, with the exception of object IDs. You can retrieve all API endpoints via Swagger to assist in programatically building a client library for the DaniWeb Connect API, or formatting the API reference document in your preferred format.

If you are writing an AJAX-based application, we offer support for JSONP, which is essentially a javascript technique that is used as an effective workaround for the same-origin policy which typically prevents web browsers from sending AJAX requests to a different domain and receiving a response. When making API calls from within javascript-based applications, be sure to pass in a callback parameter. The callback parameter allows you to receive a response in JSONP format, as opposed to a typical JSON string which is the default. JSONP, or padded JSON, wraps the result in a callback function. (You can optionally specify the name of the callback function as the parameter's value.)

HTTP Payloads

All endpoints designated within our reference document as POST require data to be submitted as such, but GET-designated endpoints will accept data via either GET or POST up through version 2 of our API. All POST requests accept either form-urlencoded parameters or a JSON payload, with the exception of batch requests which only accept a JSON payload. When sending form data, the content-type of the POST request should be set to application/x-www-form-urlencoded unless you are transmitting binary data, in which case the content-type should be set to multipart/form-data. Parameters that accept binary data indicate so. The content-type of requests consisting of a JSON payload should be set to application/json.

The preferred way to send an access token with a request is within the HTTP header as so, as it is the most secure:

Authorization: Bearer access_token_123

However, for convenience, the access_token parameter can be specified as a GET or POST parameter in the query string or HTTP body.

POST requests can be issued either by sending an HTTP payload consisting of form data or a JSON object. JSON nested objects may be created from parameters with underscores, in which the nesting may be delimited based on underscores, but does not have to be. For example, the form parameters text_raw: 'Hello' and text_parsed: '<p>Hello</p>' can be converted to the nested JSON object {"text":{"raw":"Hello","parsed":"<p>Hello</p>"}}. Alternatively, they can be represented as a JSON object in their natural format, as such: {"text_raw":"Hello","text_parsed":"<p>Hello</p>"}. JSON objects can easily be converted to/from their form data counterparts as demonstrated in this example, in which we perform a search for all users named Bob, while giving preference to those who are interested in either php or java:

POST users/searches

Form Data Payload:

profile_first_name_query=Bob&
metadata_0_key=tags&
metadata_0_query=java+OR+php&
metadata_0_weight=100

JSON Payload:

{
    "profile": {
        "first_name": {
            "query": "Bob"
        }
    },
    "metadata": [
        {
            "key": "tags",
            "query": "java OR php",
            "weight": 100
        }
    ]
}

Webhooks

Webhooks are user-defined HTTP callbacks triggered when a user becomes online, a new message is posted to a conversation or a new message is posted to a group. When such events occur, DaniWeb Connect makes an HTTP request to the callback URI configured for the webhook. Webhooks can be used to create PUSH-enhanced applications. You can register and delete webhooks via their respective API endpoints, which vary based on the API version. However, while they require an access token to be registered, they do not expire when the access token used to create them expires. Instead, they are deleted by calling the delete endpoint or, alternatively, temporarily cease working if the end-user chooses to deauthorize your application.

Array
(
    [webhook_id] => ID # of the Webhook that was triggered
    [webhook_name] => Name of the Webhook that was triggered
    [user_id] => ID # of the User who performed the action
    [event] => conversation_message OR conversation_seen OR group_message OR group_seen OR group_update OR user_online OR user_update
    [object_type] => Conversation or Group or User
    [object_id] => ID # of the Conversation or Group or User
    [timestamp] => Format similar to: 2019-06-15 20:55:33
)

PUSH notifications are sent with the following POST data for webhooks registered with version 2 or below of the API:

webhook_id=ID+%23+of+the+Webhook+that+was+triggered&
webhook_name=Name+of+the+Webhook+that+was+triggered&
user_id=ID+%23+of+the+User+who+performed+the+action&
event=conversation_message+OR+conversation_seen+OR+group_message+OR+group_seen+OR+group_update+OR+user_online+OR+user_update&
object_type=Conversation+or+Group+or+User&
object_id=ID+%23+of+the+Conversation+or+Group+or+User&
timestamp=Format+similar+to%3A+2019-06-15+20%3A55%3A33

PUSH notifications are sent with the following JSON payload for webhooks registered with version 3 or higher of the API:

{
    "event": {
        "user": {
            "id": 0
        },
        "object": {
            "type": "string",
            "id": 0
        },
        "app": {
            "id": 0
        },
        "id": 0,
        "action": "string",
        "timestamp": "string"
    },
    "webhook": {
        "id": 0,
        "name": "string"
    }
}

Batch Requests

The DaniWeb Connect API allows you to send batch requests to simultaneously perform multiple API calls. You can send batch requests by sending a POST request to https://www.daniweb.com/connect/api with a JSON-formatted payload. The content-type of the POST request should be set to: application/json.

The JSON object should be in the following format:

{
    "requests": [
        {
            "method": "Either GET or POST",
            "url": "Relative URL for the API call",
            "params": "Array of parameters",
            "version": "API Version #"
        }
    ],
    "method": "Either GET or POST",
    "url": "Relative URL for the API call",
    "params": "Array of parameters",
    "version": "API Version #"
}

Properties may be set at the "global" level or specific to an individual request. If a method, url, or version does not exist at the request level, the global version, if it exists, is used. Therefore, in practice, request-level methods, urls, and versions override anything set at the global level. The version is optional, and if ommitted, defaults to the HEAD version. The method is optional, and if ommitted, defaults to GET. Params are always merged between what is at the request level and what is at the global level. So, for example, you can set the access token param at the global level, with other endpoint-specific params at the request level. Another example might be to retrieve multiple paginated results at once, setting everything at the global level with the exception of the page param. Multiple requests within a batch are executed simultaneously, and the order in which they are processed cannot be guaranteed. Therefore, if you send a batch request to meet someone, and at the same time, fetch a list of current conversations, there is no guarantee as to whether the person just met will appear within the list of conversations. However, in generating the output, the responses for each individual request will always be presented in the same order in which they were listed in the request.

An example of the JSON payload for a request is:

{
    "requests": [
        {
            "method": "POST",
            "url": "users/1/meet",
            "params": {
                "message": "Hello World"
            }
        },
        {
            "method": "GET",
            "url": "reports/active"
        }
    ],
    "params": {
        "access_token": "abc"
    }
}

The output is presented in the following format:

{
    "data": [
        {
            "url": "string",
            "http_code": "integer",
            "response": [
                "..."
            ]
        }
    ],
    "execution_time": "float"
}