Settle Up offers API open to all developers. It's a REST-like simple API which gives you access to all data for online groups (if you have user's permission). With the API, you can create for example:

  • compatible app for iPhone, BlackBerry, Windows Phone, ...
  • tool for exporting data to Google Docs, Excel, some online service, ...

Request API Key

By requesting API Key, you understand that:
  • Server can be shut down any time, data can be lost. Author is not responsible for data loss, service shutdown and related costs (although I will try to prevent it as much as possible)
  • You need to put links to Android version on app website and application store (if possible)
  • If you use graphics, name or UI flows, the app needs to be able synchronize over this API (but it can work also offline)
Request API key via e-mail (in the e-mail describe your plans for the app)


  • REST-like API open for developers
  • Authentication by Google, Facebook or any e-mail
  • It is designed for clients to work fully offline
  • Server stores just changes, not current state of data (revert to previous state might be in the future)
  • Encoding data in JSON
  • Online IDs are generated as hash on client, server does not generate them

General format

  • Environments:
    • http://api.settleup.info - live stable API
    • http://sandbox.settleup.info - development API, use when developing application! Can be unstable, datastore can be cleared anytime
  • URL structure: http://<environment>.settleup.info/<resource>/<subresource>.<format>
  • POST for creating or updating data
  • GET for retrieving data
  • User-Agent: <app_name>/<app_version> (<platform>; <platform_version>; <user_language>)
  • X-Api-Key: <your_API_key>
Response codes:
  • 200 OK (with response data typically in JSON)
  • 204 No Content (no matching content found)
  • 400 Bad Request (wrong format of data from client)
  • 401 Unauthorized (not invited to this group or cookie expired)
  • 403 Forbidden (API key not valid)
  • 404 Not Found (calling unknown URL)
  • 419 Authentication Timeout (auth token expired, you should invalidate it on client)
  • 426 Upgrade Required (newer version of client needed to properly working)
  • 500 Internal Server Error (error on server)


Settle Up doesn't have own user accounts. For ease of use, it uses Google or Facebook login. You can implement Google or Facebook or both. In addition you should implement "any e-mail verification". That ensures that group shared from Facebook e-mail will be usable on Google e-mail etc.

Google OAuth2
  • Implement standard Google OAuth2 login according to their documentation, ask for these scopes: email, profile
  • Save access_token on device and send it with every request using this header: Authorization: google_token=<access_token>
  • If access_token is invalid or expired, you will receive HTTP 419
  • Use UserInfo API to discover user's name, email or what you need.
  • Facebook app id is: 327675517252504, contact me if you need more info about Facebok app.
  • Implement Facebook login standard way according to their documentation, ask for these permissions: email, offline_access
  • Use Graph API to discover user's name, email or what you need.
  • Save access_token on device and send it with every request using this header: Authorization: fb_token=<access_token>
  • If access_token is invalid or expired, you will receive HTTP 401 and reason in the body
Any email verification
  • Groups in Settle Up are shared with e-mails. Users can add additional e-mails to their "master" e-mail (from Facebook or Google)
  • This ensures that group can be shared with any e-mail, not just e-mails tied with Facebook or Google account
  • Server handles verification of these "slave" e-mails. Sharing to these e-mails doesn't work unless they are verified
  • Add slave email by POSTing "<new_email>" to http://<environment>.settleup.info/emails/create.json
  • List slave emails by GET http://<environment>.settleup.info/emails/list.json. Response is self-explanatory JSON with e-mails and whether they are verified.
  • Delete slave email by POSTing "<del_email>" to http://<environment>.settleup.info/emails/delete.json

Online IDs

Client is expected to work offline, so it needs to have some sort of SQL-like database. For identifying records, you need to use online IDs. Online IDs can be computed on client as hash. Therefore server does not need to generate them. Online ID of any item is generated as:

onlineID = firstTwentyChars(SHA1(<installationId>+<localId>))

  • installationId is identifying app installation. It's calculated as hash(deviceId+big_random_number) and saved first start of the app
  • localId is some id of item in local database, can be SQL autoincrement primary key, but can be anything what guarantees unique value for all data of one kind (payments, members, …)
In all client-server communication, only Online IDs are used. Never local IDs.

Create online group

Creation of online group is done by simple HTTP request. You specify basic information about the group, creator of the group and e-mails of others in the group. See Android version for recommended UI flow.

POST http://<environment>.settleup.info/groups/create.json
	"creator":{"name":"<creator_name>", "email":"<creator_email>"},		
	"name": "<name_of_the_group>",
	"language", "<language>",
	"currency": {"code":"<currency_code>", "sign":"<currency_sign>"},
	"id" : "<online_id>",
	"permissions": [
		{"name":"<member1_name>", "email":"<member1_email>"},
		{"name":"<member2_name>", "email":"<member2_email>"},
200 OK

  • *_name should be automatically fetched from contacts for given e-mail. If name is unknown, e-mail should be used.
  • name_of_the_group - if empty, it should be made of member names e.g. "Bob T., Jane M."
  • language - ISO 639-1 language code like "en"
  • currency_code - ISO 4217 currency code like "USD"
  • currency_sign - common sign for currency like "$"

Join online group

This way you can get list of groups shared with current user (and his slave e-mails). You have all information required to create group, so no need for another request. After user joins the group, you should immediately start first synchronization.

GET http://<environment>.settleup.info/groups/list.json
200 OK
	{"id":"<group_online_id>", "name":"<group_name>", 
		"currency": {"code":"<currency_code>", "sign":"<currency_sign>"}},
	{"id":"<group_2_online_id>", "name":"<group_2_name>", 
		"currency": {"code":"<currency_code>", "sign":"<currency_sign>"}},
204 No Content (no matching group found)


Synchronization is again just one HTTP request. It's meant to be done periodically, for example every hour. Only current group is synchronized. Sync works with changes, they are very general and can be used for any data table. However current Android version works with tables "payments", "members" and "groups". Specification of data inside these tables are in Tips for developing Settle Up for other platform.

In every sync, this is sent to server:
  • list of changes done since last successful sync with client timestamps
  • online group id
  • last successful sync timestamp in server time (null if unknown)
  • Data version (server will use it for handling compatibility)
Server checks if user has permission to access group and sends back:
  • list of changes waiting on the server from other users
  • new last sync timestamp (server time) which should be saved on client. Pending changes on client should be deleted.
Expected behavior:
  • Changes are three types: insert, update or delete. Always inserts needs to be performed first, then updates, then deletes.
  • For inserts: First insert members, then insert payments. (it can happen that payment contains reference to not-yet-existing member)
  • It can happen, that server sends update or delete change to non-existing record. It that case change should be ignored
  • Update conflicts (more people edit same record before sync) are resolved automatically on the server. Client timestamps are used for comparison of conflicted updates. Who edited record last wins and other versions are discarded.
  • Users should be notified by default about changes done by sync - at least payment insert/update/delete.
POST http://<environment>.settleup.info/groups/<group_online_id>/changes.json
200 OK
  • last_sync_timestamp is in server time. In first sync it's null (downloads all changes), next time it's value saved from last sync.
  • data_table - currently "payments", "members" or "groups"
  • client_timestamp - UNIX time in millis - number of milliseconds since 1.1.1970
  • data_values - key-value data encoded as JSON object. Must be escaped to string. See data structures for tables in Tips for developing Settle Up for other platform.

Additional methods

  • Grant permission later
    • POST {"name":"..","email":"..","language":".."}
    • to http://<environment>.settleup.info/groups/<group_online_id>/permissions/create.json
  • Remove permission later
    • POST "<email_to_remove>"
    • to http://<environment>.settleup.info/groups/<group_online_id>/permissions/delete.json
  • Deleting group online
    • POST to http://<environment>.settleup.info/groups/<group_online_id>/delete.json


Want to see API in action?
  • Current Android version puts all HTTP requests into Android logs. Download Android SDK, set your phone to debug mode and see ADB log.
  • If you don't want to install Android SDK, install app Log Collector. You can see logs in the app.

Tips for developing for other platform

Are you developing iPhone, BlackBerry or Windows Phone app compatible with Settle Up? Read this page, it will be useful. Settle Up is designed to work offline, so there is quite a lot of work for client developer. I will try to speed it up and help you.

Intent API

Android app offers Intent API for other apps since v6.1. You can create a payment in your app and save it to Settle Up. Here is a working code & documentation of the API:
Intent intent = new Intent("cz.destil.settleup.NEW_PAYMENT");
intent.putExtra("amount", 5.5);
intent.putExtra("currency", "CZK"); // 3-chars ISO code
intent.putExtra("purpose", "Test");
intent.putExtra("datetime", System.currentTimeMillis() - 2 * 3600 * 1000); // two days ago
intent.putExtra("transfer", true); // transfer means that payment doesn't count into Total paid
try {
	startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
	startActivity(new Intent(Intent.ACTION_VIEW, Uri

Note: You can ommit any intent extra, default values will be used.