Pushwoosh is just the solution we were looking for. What can I say, it does exactly what it says in the tin. It dropped straight into our game with no effort and now our game users send and receive notifications to and from each other. From HQ, we are also able send notifications to targeted users or groups of users.

It's really brought our game alive and improved retention enormously.

Kevin Cook

Programming Director

PixelFlip Media Ltd.

READ TESTIMONIAL

Remote API Guide

JSON API 1.3

Service URL is https://cp.pushwoosh.com/json/1.3/%method%

Send POST method with the JSON data as per API below. The total size of the POST request must not exceed 10Mb.

Some methods need you to provide Auth Token, create this token at https://cp.pushwoosh.com/api_access.


Method /createMessage

Creates new push notification

Request:

{
   "request":{
      "application":"APPLICATION_CODE",
      "applications_group":"GROUP_CODE",       // Optional. Can be used instead of "application"
      "auth":"api_access_token",
      "notifications":[
         {
            // Content settings 
            "send_date":"now",           // YYYY-MM-DD HH:mm  OR 'now'
            "ignore_user_timezone": true,   // or false
            "content":{                  // Object( language1: 'content1', language2: 'content2' ) OR string
               "en":"English",
               "ru":"Русский",
               "de":"Deutsch"
            }, 
            "page_id": 39,               // Optional. int
            "link": "http://google.com", // Optional. string
            "minimize_link": 0,  // Optional param:  0 or false - not minimize, 1 - google, 2 - bitly, 3 - baidu (china) . Default = 1 
            "data":{                     // JSON string or JSON object, will be passed as "u" parameter in the payload
                  "custom": "json data"
            }
            "platforms": [1,2,3,4,5,6,7,8,9,10], // 1 - iOS; 2 - BB; 3 - Android; 5 - Windows Phone; 7 - OS X; 8 - Windows 8; 9 - Amazon; 10 - Safari

            // iOS related
            "ios_badges": 5,               // Optional. Integer. This value will be sent to ALL devices given in "devices"
            "ios_sound": "sound file.wav",    // Optional. Sound file name in the main bundle of application
            "ios_root_params": {"content-available":1}, //Optional - root level parameters to the aps dictionary
            "apns_trim_content":1,     // Optional. (0|1) Trims the exceeding content strings with ellipsis
            "ios_trim_content": 1,       // Depricated, use "apns_trim_content" instead.

            // Android related
            "android_root_params": {"key": "value"}, // custom key-value object. root level parameters for the android payload recipients
            "android_sound" : "soundfile", // Optional. Sound file name in the "res/raw" folder, do not include the extension
            "android_header":"header",    // Optional. Android notification header
            "android_icon": "icon.png",
            "android_custom_icon": "http://example.com/image.png", // Optional. Full path URL to the image file
            "android_banner": "http://example.com/banner.png", // Optional. Full path URL to the image file
            "android_gcm_ttl": 3600, // Optional. Time to live parameter - the maximum lifespan of a message in seconds

            // Amazon related
            "adm_root_params": {"key": "value"}, // custom key-value object
            "adm_sound": "push.mp3",
            "adm_header": "Header",
            "adm_icon": "icon.png",
            "adm_custom_icon": "http://example.com/image.png",
            "adm_banner": "http://example.com/banner.png",

            // Windows Phone related.
            "wp_type": "Tile",           // notification type. 'Tile' or 'Toast'. Raw notifications are not supported. 'Tile' if default 
            "wp_background": "/Resources/Red.jpg", // Tile image
            "wp_backbackground": "/Resources/Green.jpg", // Back tile image
            "wp_backtitle": "back title",  // Back tile title 
            "wp_count": 3,               // Optional. Integer. Badge for notification

            // Mac OS X related
            "mac_badges": 3,
            "mac_sound": "sound.caf",
            "mac_root_params": {"content-available":1},

            // WNS related
            "wns_content": { // Content (XML or raw) of notification encoded in MIME's base64 in form of Object( language1: 'content1', language2: 'content2' ) OR String
               "en": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48YmFkZ2UgdmFsdWU9ImF2YWlsYWJsZSIvPg==",
               "de": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48YmFkZ2UgdmFsdWU9Im5ld01lc3NhZ2UiLz4="
            },
            "wns_type": "Badge", // 'Tile' | 'Toast' | 'Badge' | 'Raw'
            "wns_tag": "myTag", // Optional. Used in the replacement policy of the Tile. An alphanumeric string of no more than 16 characters.

             // Safari related
            "safari_title": "Title", // Title of the notification
            "safari_action": "Click here", // Optional
            "safari_url_args": ["firstArgument", "secondArgument"], // Optional if your application url template has no placeholders 


            "devices":[                  // Optional. If set, message will only be delivered to the devices in the list. Ignored if the applications group is used
               "dec301908b9ba8df85e57a58e40f96f523f4c2068674f5fe2ba25cdc250a2a41"
            ],
            "filter": "FILTER_NAME" //Optional.
            "conditions": [TAG_CONDITION1, TAG_CONDITION2, ..., TAG_CONDITIONN] //Optional. See remark
         }
      ]
   }
}

Parameters:

auth – API access token from the Pushwoosh control panel (create this token at https://cp.pushwoosh.com/api_access)

application – your Pushwoosh application ID where you send the message to (cannot be used together with “applications_group”)

applications_group – your Pushwoosh Application group code (cannot be used together with “application”)

content – is the text push message delivered to the application

data – use this only if you want to pass custom data to the application (JSON format) or omit this parameter. Please note that iOS push is limited to 256 bytes

page_id – HTML page id (created from Application’s HTML Pages). Use this if you want to deliver additional HTML content to the application or omit this parameter

send_date – set the time you want the message to be sent (in UTC) or use ‘now’ to send it immediately

wp_count – sets the badge for WP7 platform.

ios_badges – sets the badge on the icon for iOS platform. This value will be sent to ALL devices given in the “devices” list. If you want to have different badge for each device you need to create another entry in the “notifications” array.

(This has been changed from API 1.2 behavior)

devices – omit this field (push notification will be delivered to all the devices for the application), or provide the list of devices IDs as described

ios_root_params – root level parameters to the aps dictionary. For example to use with NewsStand apps.

condition – Tag condition is an array like: [tagName, operator, operand], where

  • tagName: string
  • operator: “LTE”|”GTE”|”EQ”|”BETWEEN”|”IN”
  • operand: string|integer|array

Valid operators for String tags:

  • EQ: tag value equals to operand. Operand must be a string.

Valid operators for Integer tags:

  • GTE: tag value greater then or equals to operand. Operand must be an integer;
  • LTE: tag value less then or equals to operand. Operand must be an integer;
  • EQ: tag value equals to operand. Operand must be an integer;
  • BETWEEN: tag value greater then or equals to min_operand value and tag value less then or equals to max operand value. Operand must be an array like: [min_value, max_value].

Valid operators for List tags:

  • IN: Intersect user values and operand. Operand must be an array of strings like: ["value 1", "value 2", "value N"].

You cannot use “filter” and “conditions” parameters together.

Country and Language tags:

Language tag value is lowercase two-letter code according to the ISO-639-1 table: http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes

Country tag value is an uppercase two-letter code according to the ISO_3166-2 table: http://en.wikipedia.org/wiki/ISO_3166-2

For example to send push notification to subscribers in Brazil that speaks Portuguese language you need to specify condition like this:

"conditions": [["Country", "EQ", "BR"],["Language", "EQ", "pt"]]

Response:

{
   "status_code":200,
   "status_message":"OK",
   "response": {
      "Messages":["{Notification code}", "{Notification code}", ...] // One for each notification object 
   }  
}

Status codes

HTTP Status code status_code Description
200 200 Message successfully created
200 210 Argument error. See status_message for more info
400 N/A Malformed request string
500 500 Internal error

Method /deleteMessage

Deletes the message

Request:

{
   "request":{
      "auth":"api_access_token",
      "message": "Message code obtained in createMessage"
   }
}

Response:

{
   "status_code":200,
   "status_message":"OK"
}

Status codes:

HTTP Status code status_code Description
200 200 Message successfully deleted
200 210 Argument error. See status_message for more info
400 N/A Malformed request string
500 500 Internal error

Method /registerDevice

Registers device for the application

Request:

{
   "request":{
      "application":"APPLICATION_CODE",
      "push_token":"DEVICE_PUSH_TOKEN",
      "language":"en",  // optional
      "hwid": "hardware device id",
      "timezone": 3600, // offset in seconds 
      "device_type":1
   }
}

Parameters:

application – your Pushwoosh application ID where you send the message to

push_token – Push token for the device

language – Language locale of the device (optional)

hwid – Unique string to identify the device (Please note that accessing UDID on iOS is deprecated and not allowed, one of the alternative ways now is to use MAC address)

timezone – Timezone offset in seconds for the device (optional)

device_type – 1 – iphone, 2 – blackberry, 3 – android, 4 – nokia, 5 – WP7, 7 – mac

Response:

{
   "status_code":200,
   "status_message":"OK"
   "response": null
}

Status codes:

HTTP Status code status_code Description
200 200 Device successfully registered
200 210 Argument error. See status_message for more info
400 N/A Malformed request string
500 500 Internal error

Method /unregisterDevice

Remove device from the application

Request:

{
   "request":{
      "application":"APPLICATION_CODE",
      "hwid": "hardware device id"
   }
}

Parameters:

application – your Pushwoosh application ID where you send the message to

hwid – hardware device id used in registerDevice function call

Response:

{
   "status_code":200,
   "status_message":"OK"
}

Error status codes:

HTTP Status code status_code Description
200 200 Device successfully unsubscribed
200 210 Argument error. See status_message for more info
400 N/A Malformed request string
500 500 Internal error

Method /setTags

Set tags values for device

Request:

{
   "request":{
      "application":"DEAD0-BEEF0",
      "hwid": "device hardware id",
      "tags": {
           "tag1": "string value",
           "tag2": 42,
           "tag3": "string"
      }  
   }
}

Parameters:

application – your Pushwoosh application ID where you send the message to

hwid – hardware device id used in registerDevice function call

tags – tags to set

Sample response:

{
   "status_code":200,
   "status_message":"OK"
   "response": null
}

Status codes

HTTP Status code status_code Description
200 200 Tags set succcessfully
200 210 Argument error. See status_message for more info
400 N/A Malformed request string
500 500 Internal error

Method /setBadge

Set current badge value for the device to let auto-incrementing badges work properly.

Request:

{
   "request":{
      "application":"DEAD0-BEEF0",
      "hwid": "device hardware id",
      "badge": 5
      }  
   }
}

Parameters:

application - your Pushwoosh application ID where you send the message to

hwid - hardware device id used in registerDevice function call

badge - current badge on the application to use with auto-incrementing badges

Sample response:

{
   "status_code":200,
   "status_message":"OK"
}

Method /pushStat

Register push open event

Request:

{
   "request":{ 
      "application": "DEAD0-BEEF0", 
      "hwid": "HWID", 
      "hash": "hash"         // received in the push notification in the "p" parameter
   }
}

Parameters:

application - your Pushwoosh application ID where you send the message to

hwid - hardware device id used in registerDevice function call

hash - hash tag received in push notification

Sample response:

{
   "status_code":200,
   "status_message":"OK"
}

Method /getNearestZone

Records device location for geo push notifications

Request:

{
   "request":{
      "application": "DEAD0-BEEF0",
      "hwid": "HWID",
      "lat": 10.12345,
      "lng": 28.12345
   }
}

Parameters:

application - your Pushwoosh application ID where you send the message to

hwid - hardware device id used in registerDevice function call

lat - latitude of the device

lng - longitude of the device

Sample response:

{
   "status_code":200,
   "status_message":"OK"
   "response": {  //nearest zone to the position provided in the request
      "name":"zone name",
      "lat":"42",
      "lng":"42",
      "distance":4715784 // distance in meters
   }
}

Global error codes

  • 500 - Bad request(Can't parse json)
  • 501 - Method not implemented

BASH sample script:

#!/bin/bash

#Usage
if [ ! -n "$1" ] || [ ! -n "$2" ]
then
  echo "`basename $0` usage: api_token appid message";
  exit 1;
fi;
MESSAGE="$3";
if [ -z "$3" ]
then
MESSAGE='One push to rule them all!'
fi;

echo -e "Response:"
curl --data-binary "
{\"request\":
	{\"application\":\"$2\",
	 \"auth\":\"$1\",
	 \"notifications\":
		[{
                        \"send_date\": \"now\",
			\"content\": \"$MESSAGE\"
		}]
	}
}" \
-H "Content-type: application/json" \
"https://cp.pushwoosh.com/json/1.3/createMessage"
echo"";
exit 0;
This sample requires libcurl installed.

PHP sample code:

<?php

	define('PW_AUTH', 'API TOKEN');
	define('PW_APPLICATION', 'APPLICATION CODE');

	function doPostRequest($url, $data, $optional_headers = null) {
		$params = array(
			'http' => array(
				'method' => 'POST',
				'content' => $data
			));
		if ($optional_headers !== null)
			$params['http']['header'] = $optional_headers;

		$ctx = stream_context_create($params);
		$fp = fopen($url, 'rb', false, $ctx);
		if (!$fp)
			throw new Exception("Problem with $url, $php_errmsg");

		$response = @stream_get_contents($fp);
		if ($response === false)
			return false;
		return $response;
	}

	function pwCall( $action, $data = array() ) {
		$url = 'https://cp.pushwoosh.com/json/1.3/' . $action;
		$json = json_encode( array( 'request' => $data ) );
		$res = doPostRequest( $url, $json, 'Content-Type: application/json' );
		print_r( @json_decode( $res, true ) );
	}

	pwCall( 'createMessage', array(
		'application' => PW_APPLICATION,
		'auth' => PW_AUTH,
		'notifications' => array(
					array(
						'send_date' => 'now',
						'content' => 'test',
						'ios_badges' => 3,
						'data' => array( 'custom' => 'json data' ),
						'link' => 'http://pushwoosh.com/'
					)
				)
			)
		);
?>
Make sure you are sending JSON Object serialized into string. Not the JSON string itself. The latter will add escape symbols before quotation marks (like \") resulting in BAD_REQUEST error.

.NET sample code:

The code below uses "json.net" library.

using System;
using System.IO;
using System.Net;
using Newtonsoft.Json.Linq;

namespace WebApplication1
{
   public partial class Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           string pwAuth = "YOUR_AUTH_TOKEN";
           string pwApplication = "PW_APPLICATION_CODE";
           JObject json = new JObject(
               new JProperty("application", pwApplication),
               new JProperty("auth", pwAuth),
               new JProperty("notifications",
                   new JArray(
                       new JObject(
                           new JProperty("send_date", "now"),
                           new JProperty("content", "test"),
                           new JProperty("wp_type", "Toast"),
                           new JProperty("wp_count", 3),
                           new JProperty("data",
                               new JObject(
                                   new JProperty("custom", "json data"))),
                           new JProperty("link", "http://pushwoosh.com/"),
                           new JProperty("conditions",
                               new JArray(
                                   (object)new JArray("Color", "EQ", "black")))))));
           PWCall("createMessage", json);
       }
       private void PWCall(string action, JObject data)
       {
           Uri url = new Uri("https://cp.pushwoosh.com/json/1.3/" + action);
           JObject json = new JObject(new JProperty("request", data));
           DoPostRequest(url, json);
       }
       private void DoPostRequest(Uri url, JObject data)
       {
           HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
           req.ContentType = "text/json";
           req.Method = "POST";
           using (var streamWriter = new StreamWriter(req.GetRequestStream()))
           {
               streamWriter.Write(data.ToString());
           }
           HttpWebResponse httpResponse;
           try
           {
               httpResponse = (HttpWebResponse)req.GetResponse();
           }
           catch (Exception exc)
           {
               throw new Exception(string.Format("Problem with {0}, {1}", url, exc.Message));
           }
           using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
           {
               var responseText = streamReader.ReadToEnd();
               Page.Response.Write(responseText);
           }
       }
   }
}

Erlang sample code:


-module(pushwoosh).
-export([run/0, stop/0, sendMessage/1]).
%% sendMessage argument: message text %%

%% Authentication & App_id %%
-define(PW_AUTH, "YOUR_AUTH_TOKEN").
-define(PW_APPLICATION, "YOUR_PUSHWOOSH_APP_CODE").

%% KickStart %%
run() ->
	application:start(unicode),
	application:start(crypto),
	application:start(public_key),
	application:start(ssl),
	application:start(inets),
	%% HTTP Client verbosity options flase, verbose, debug
	httpc:set_options([{verbose, false}]).  
stop() ->
	application:stop(ssl),
	application:stop(public_key),		
	application:stop(crypto),
	application:stop(inets).
%% JSON Wars !
encode(S) -> encode(S, [$"]).
encode([], Acc) -> lists:reverse([$" | Acc]);
encode([C | Cs], Acc) ->
        Hex = lists:flatten(io_lib:format("~4.16.0b", [C])),
        encode(Cs, lists:reverse(Hex) ++ "u\\" ++ Acc).

sendMessage(Message_text) ->
	%% URL to JSON API 1.3
	Url = "https://cp.pushwoosh.com/json/1.3/createMessage",
	EncodedMessage = encode(Message_text),
	{ok, Response} = httpc:request(
		%%Method 
		post, 
		%%Request
		{Url, [{"User-Agent", "Erlang exemple"}], "application/json; charset=UTF-8", 
		"{\"request\":{
		\"application\": \""?PW_APPLICATION"\",
		\"auth\": \""?PW_AUTH"\",
		\"notifications\": [{
		\"send_date\": \"now\",
		\"content\": "++EncodedMessage++"
		}]}}"},
		%%HTTP options
		[{ssl,[{verify, verify_none}]}, {version, "HTTP/1.0"}],
		%%Options
		[]),
	io:format("And received ~p", [Response]).

Ruby sample code:

Thanks to Alexandre Toulemonde

class PushNotification
  
  #- PushWoosh API Documentation http://www.pushwoosh.com/programming-push-notification/pushwoosh-push-notification-remote-api/ 
  #- Two methods here:
  #     - PushNotification.new.notify_all(message) Notifies all with the same option
  #     - PushNotification.new.notify_devices(notification_options = {}) Notifies specific devices with custom options
    
  include HTTParty #Make sure to have the HTTParty gem declared in your gemfile https://github.com/jnunemaker/httparty
  default_params :o utput => 'json'
  format :json
  
  def initialize
    #- Change to your settings
    @auth = {:application  => "00000-00000",:auth => "auth_token"}
  end 
  
  # PushNotification.new.notify_all("This is a test notification to all devices")
  def notify_all(message)
    notify_devices({:content  => message})
  end
  
  # PushNotification.new.notify_device({
  #  :content  => "TEST",
  #  :data  => {:custom_data  => value},
  #  :devices  => array_of_tokens
  #})
  def notify_devices(notification_options = {})
    #- Default options, uncomment :data or :devices if needed
    default_notification_options = {
                        # YYYY-MM-DD HH:mm  OR 'now'
                        :send_date  => "now",
                        # Object( language1: 'content1', language2: 'content2' ) OR string
                        :content  => {
                            :fr  => "Test",
                            :en  => "Test"
                        },
                        # JSON string or JSON object "custom": "json data"
                        #:data  => {
                        #    :custom_data  => value
                        #},
                        # omit this field (push notification will be delivered to all the devices for the application), or provide the list of devices IDs
                        #:devices  => {}
                      }
                      
    #- Merging with specific options
    final_notification_options = default_notification_options.merge(notification_options)

    #- Constructing the final call
    options = @auth.merge({:notifications  => [final_notification_options]})
    options = {:request  => options}                                                                                                                             
    #- Executing the POST API Call with HTTPARTY - :body => options.to_json allows us to send the json as an object instead of a string
    response = self.class.post("https://cp.pushwoosh.com/json/1.3/createMessage", :body  => options.to_json,:headers => { 'Content-Type' => 'application/json' })
  end
end

Java sample code:

Uses JSON classes from http://json.org/java/

package com.arellomobile;

import org.json.*;
import java.io.*;
import java.net.*;

public class SendPushNotificationSample
{
	public static final String PUSHWOOSH_SERVICE_BASE_URL = "https://cp.pushwoosh.com/json/1.3/";
	private static final String AUTH_TOKEN = "YOUR_AUTH_TOKEN";
	private static final String APPLICATION_CODE = "PW_APPLICATION_CODE";

	public static void main(String[] args) throws JSONException, MalformedURLException
	{
		String method = "createMessage";
		URL url = new URL(PUSHWOOSH_SERVICE_BASE_URL + method);

		JSONArray notificationsArray = new JSONArray()
				.put(new JSONObject().put("send_date", "now")
									 .put("content", "test")
									 .put("link", "http://pushwoosh.com/"));

		JSONObject requestObject = new JSONObject()
				.put("application", APPLICATION_CODE)
				.put("auth", AUTH_TOKEN)
				.put("notifications", notificationsArray);

		JSONObject mainRequest = new JSONObject().put("request", requestObject);
		JSONObject response = SendServerRequest.sendJSONRequest(url, mainRequest.toString());

		System.out.println("Response is: " + response);
	}
}

class SendServerRequest
{
	static JSONObject sendJSONRequest(URL url, String request)
	{
		HttpURLConnection connection = null;
		try
		{
			connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("POST");
			connection.setRequestProperty("Content-Type", "application/json");
			connection.setDoInput(true);
			connection.setDoOutput(true);

			DataOutputStream writer = new DataOutputStream(connection.getOutputStream());
			writer.writeBytes(request);
			writer.flush();
			writer.close();

			return parseResponse(connection);
		}
		catch (Exception e)
		{
			System.out.println("An error occurred: " + e.getMessage());
			return null;
		}
		finally
		{
			if (connection != null)
			{
				connection.disconnect();
			}
		}
	}

	static JSONObject parseResponse(HttpURLConnection connection) throws IOException, JSONException
	{
		String line;
		BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		StringBuilder response = new StringBuilder();

		while ((line = reader.readLine()) != null)
		{
			response.append(line).append('\r');
		}
		reader.close();

		return new JSONObject(response.toString());
	}
}