Payments and Payouts for Open Work
Python CSS JavaScript PLpgSQL HTML Shell Other
Latest commit 621cd9e Oct 22, 2016 @whit537 whit537 Bump version to 1987
Failed to load latest commit information.
.tx I renamed the Transifex project Oct 28, 2014
bin Replace outdated masspay docstring with a link Sep 1, 2016
data Update PayPal entry Jul 6, 2015
docs Clean out docs/gratipay each time we build it Jul 28, 2016
emails Add a notification when identity is viewed May 12, 2016
gratipay Use stdin pipe with communicate instead of echo. Oct 22, 2016
i18n update i18n files Oct 22, 2016
img-src png images recompress losslessly Mar 13, 2016
js Remove previous click handlers from confirm events. Aug 9, 2016
scripts Update dependency docs in light of #3994 May 14, 2016
scss Roll our own confirm instead of using browser's Aug 9, 2016
sql Minor formatting cleanups Aug 31, 2016
templates Make it easier to tag pages for special css Oct 20, 2016
tests Add marky test. Oct 22, 2016
vendor Add a `make doc` and fix all WARNINGS Jul 28, 2016
www Bump version to 1987 Oct 22, 2016
.babel_extract collect i18n messages from the gratipay lib Feb 11, 2015
.editorconfig Visually optimize a glob in our .editorconfig Jan 30, 2014
.gitattributes Enforce Unix line endings on Windows. Jan 5, 2014
.gitignore Port one test from Dalek to Splinter Jul 12, 2016
.slugignore Remove Node dependency Jul 12, 2016
.travis.yml Ask travis to install marky. Oct 22, 2016
401.spt Make the 401 page neater Sep 7, 2015
410.spt i18n of `410.spt` Feb 26, 2015 More text Dec 15, 2015
COPYING rename Gittip to Gratipay Aug 26, 2014
Dockerfile README normalization Feb 4, 2016
Makefile Report on TTW and Python tests together Jul 28, 2016
Procfile Hide gunicorn version Jun 14, 2016 Remove Node dependency Jul 12, 2016
Vagrantfile Move ./bin/ to ./scripts/ May 10, 2015 rename Gittip to Gratipay Aug 26, 2014
defaults.env Comment CRYPTO_KEYS May 9, 2016
error.spt Don't require _ in error.spt Aug 30, 2015 Upgrade virtualenv 1.11.6 -> 12.0.7 (#3268) Mar 24, 2015 Hide gunicorn version Jun 14, 2016 Specify heroku app in Jan 21, 2016 Fix how payday checks for required commands Apr 7, 2016 Update path to sql files in a few more places Feb 27, 2015 Adapt to a minor Heroku CLI change Dec 4, 2015 Add a `make doc` and fix all WARNINGS Jul 28, 2016
requirements.txt upgrade point release of Cryptography May 8, 2016
runtime.txt Upgrade Python Jun 7, 2016 fix pyflakes warnings Mar 26, 2015

Welcome to Gratipay

Build Status Open Bounties

Gratipay provides payments and payouts for open work, in order to cultivate an economy of gratitude, generosity, and love.


Scope Location
customer-facing pages
policies, procedures, etc.
installation You're there! Read on ...

Quick Start


Given Python 2.7, Postgres 9.3, and a C/make toolchain:

git clone
make schema data

And then run

make run

to boot the app and/or:

make test

to run the tests.

Read more.


Given VirtualBox 4.3 and Vagrant 1.7.x:

vagrant up

Read more.


Given some version(?) of Docker:

docker build -t gratipay .
docker run -p 8537:8537 gratipay

Read more.

Table of Contents


Thanks for hacking on Gratipay! Be sure to review CONTRIBUTING as well if that's what you're planning to do.


Building requires Python 2.7, and a gcc/make toolchain.

All Python library dependencies are bundled in the repo (under vendor/). If you are receiving issues from psycopg2, please ensure that its needs are met.

On Debian or Ubuntu you will need the following packages:

sudo apt-get install postgresql-9.3 postgresql-contrib libpq-dev python-dev libffi-dev libssl-dev

On OS X you can download Postgres directly or install through Homebrew:

brew install postgresql

To configure local Postgres create default role (if it hasn’t been created already) and database.

sudo -u postgres createuser --superuser $USER
createdb gratipay

If you are getting an error about unknown argument: '-mno-fused-madd' when running make, then add Wno-error=unused-command-line-argument-hard-error-in-future to your ARCHFLAGS environment variable and run make clean env again (see this Stack Overflow answer for more information):

ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future make clean env


All Python dependencies (including virtualenv) are bundled with Gratipay in the vendor/ directory. Gratipay is designed so that you don't manage its virtualenv directly and you don't download its dependencies at build time.

The included Makefile contains several targets. Configuration options are stored in default_local.env file while overrides are in local.env.

To create virtualenv enviroment with all python dependencies installed in a sandbox:

make env

If you haven't run Gratipay for a while, you can reinstall the dependencies:

make clean env

Add the necessary schemas and insert dummy data into postgres:

make schema
make fake


Once you've installed Python and Postgres and set up a database, you can use make to build and launch Gratipay:

make run

If you don't have make, look at the Makefile to see what steps you need to perform to build and launch Gratipay. The Makefile is pretty simple and straightforward.

If Gratipay launches successfully it will look like this:

$ make run
PATH=env/bin:{lots-more-of-your-own-PATH} env/bin/honcho run -e defaults.env,local.env web
2014-07-22 14:53:09 [1258] [INFO] Starting gunicorn 18.0
2014-07-22 14:53:09 [1258] [INFO] Listening at: (1258)
2014-07-22 14:53:09 [1258] [INFO] Using worker: sync
2014-07-22 14:53:09 [1261] [INFO] Booting worker with pid: 1261
pid-1261 thread-140735191843600 (MainThread) Reading configuration from defaults, environment, and command line.
pid-1261 thread-140735191843600 (MainThread)   changes_reload         False                          default
pid-1261 thread-140735191843600 (MainThread)   changes_reload         True                           environment variable ASPEN_CHANGES_RELOAD=yes
pid-1261 thread-140735191843600 (MainThread)   charset_dynamic        UTF-8                          default
pid-1261 thread-140735191843600 (MainThread)   charset_static         None                           default
pid-1261 thread-140735191843600 (MainThread)   configuration_scripts  []                             default
pid-1261 thread-140735191843600 (MainThread)   indices                [u'index.html', u'index.json', u'index', u'index.html.spt', u'index.json.spt', u'index.spt'] default
pid-1261 thread-140735191843600 (MainThread)   list_directories       False                          default
pid-1261 thread-140735191843600 (MainThread)   logging_threshold      0                              default
pid-1261 thread-140735191843600 (MainThread)   media_type_default     text/plain                     default
pid-1261 thread-140735191843600 (MainThread)   media_type_json        application/json               default
pid-1261 thread-140735191843600 (MainThread)   project_root           None                           default
pid-1261 thread-140735191843600 (MainThread)   project_root           .                              environment variable ASPEN_PROJECT_ROOT=.
pid-1261 thread-140735191843600 (MainThread)   renderer_default       stdlib_percent                 default
pid-1261 thread-140735191843600 (MainThread)   show_tracebacks        False                          default
pid-1261 thread-140735191843600 (MainThread)   show_tracebacks        True                           environment variable ASPEN_SHOW_TRACEBACKS=yes
pid-1261 thread-140735191843600 (MainThread)   www_root               None                           default
pid-1261 thread-140735191843600 (MainThread)   www_root               www/                           environment variable ASPEN_WWW_ROOT=www/
pid-1261 thread-140735191843600 (MainThread) project_root is relative to CWD: '.'.
pid-1261 thread-140735191843600 (MainThread) project_root set to /Users/whit537/personal/gratipay/
pid-1261 thread-140735191843600 (MainThread) Found plugin for renderer 'jinja2'
pid-1261 thread-140735191843600 (MainThread) Won't log to Sentry (SENTRY_DSN is empty).
pid-1261 thread-140735191843600 (MainThread) Renderers (*ed are unavailable, CAPS is default):
pid-1261 thread-140735191843600 (MainThread)   stdlib_percent
pid-1261 thread-140735191843600 (MainThread)   json_dump
pid-1261 thread-140735191843600 (MainThread)   stdlib_format
pid-1261 thread-140735191843600 (MainThread)   JINJA2
pid-1261 thread-140735191843600 (MainThread)   stdlib_template

You should then find this in your browser at http://localhost:8537/:


Congratulations! Sign in using Twitter or GitHub and you're off and running. At some point, try running the test suite.


Gratipay's default configuration lives in defaults.env. If you'd like to override some settings, create a file named local.env to store them.

The following explains some of the content of that file:

The GITHUB_* keys are for a gratipay-dev application in the Gratipay organization on Github. It points back to localhost:8537, which is where Gratipay will be running if you start it locally with make run. Similarly with the TWITTER_* keys, but there they required us to spell it

If you are running Gratipay somewhere other than localhost:8537, then you'll need to set BASE_URL, but your options are limited because we use proprietary fonts from, and they filter by Referer. You won't get the right fonts unless you use an approved domain. We've configured as well as localhost, so if you don't want to run on localhost then configure in your /etc/hosts file and set this in local.env:


If you wish to use a different username or database name for the database, you should override the DATABASE_URL in local.env using the following format:

DATABASE_URL=postgres://<username>@localhost/<database name>

We use Amazon Web Services' Simple Email Service (AWS SES) for sending emails. In development, we dump outbound mail to the console by default. This is fine if all you need to do is, e.g., copy/paste verification links. If you need to receive emails within a proper mail client during development, then sign up for AWS's free tier and override the AWS_* credentials from defaults.env in your local.env. You'll have to verify the email addresses you want to receive email with on SES.


Vagrant provides a convenient interface to VirtualBox to run and test Gratipay in virtual machine. This may be handy if you're on Windows.

You will need Vagrant and VirtualBox installed. On Linux you may need to install nfs-kernel-server as well.

With Vagrant, you can run Gratipay by running vagrant up from the project directory. Please note that if you ever switch between running Gratipay on your own machine to Vagrant or vice versa, you will need to run make clean.

The Vagrantfile will download a pristine Ubuntu image (base box), save it, and create a virtual machine (VM) in VirtualBox. Then it will set up Gratipay prerequisites (the process is known as "provisioning") and show a welcome message.

The next time you run vagrant up, it will reuse the VM. Vagrant uses SSH based authentication. To login to VM, use the vagrant ssh command. If you're prompted for a password when logging in, please use vagrant.

Mac users: If you're prompted for a password during initial installation, it's sudo and you should enter your Mac OS password.

Ubuntu users: If you experience problems, please see this issue. As mentioned there, you will also need to be wary of projects that are nested in encrypted directories.


You can also install/run Gratipay with Docker.

Build it with the included Dockerfile:

$ git clone
$ cd
$ docker build -t gratipay .

Once you've built the image, you can launch a container:

$ docker run -d -p 8537:8537 gratipay

Check it out at localhost:8537!

To edit files and have those changes reflect in the running container, mount your local folder when you execute the run command:

$ docker run -d -v $PWD:/srv/ -p 8537:8537 gratipay

You can get the running container's ID with docker ps. With that, you can

  • view the logs:
$ docker logs [container_id]
  • run commands within the project root:
$ docker exec [container_id] make schema
$ docker exec [container_id] make fake

Once you're done, kill the running container:

$ docker kill [container_id]


If you get stuck somewhere along the way, make an issue here on GitHub.

Thanks for installing Gratipay! 😃

Modifying CSS and JavaScript

We use SCSS, with files stored in scss/. All of the individual files are combined in scss/gratipay.scss which itself is compiled by libsass in www/assets/gratipay.css.spt on each request (it's behind a CDN in production).

We use a similar pattern for JavaScript. Individual files are in js/, and they're concatenated on the fly (and put behind a CDN in production) in www/assets/gratipay.js.spt

Modifying the Database

We write SQL, specifically the PostgreSQL variant. We keep our database schema in schema.sql, and we write schema changes for each PR branch in a sql/branch.sql file, which then gets run against production and merged into sql/schema.sql during deployment.

Testing Build Status

Our test suite is divided into through-the-web (TTW) tests and Python tests. You need to install PhantomJS separately in order to run the TTW tests. For both suites we use the pytest test runner; it's installed automatically as part of make env.

The easiest way to run the whole test suite is:

make test

You can also do:

make ttwtest


make pytest

To invoke py.test directly you should use the honcho utility that comes with the install. First make tests/env, the activate the virtualenv by running source env/bin/activate, and then:

[gratipay] $ cd tests/
[gratipay] $ honcho run -e defaults.env,local.env py.test

Be careful! The test suite deletes data in all tables in the public schema of the database configured in your testing environment.

Local Database Setup

For the best development experience, you need a local installation of Postgres. The best version of Postgres to use is 9.3.5, because that's what we're using in production at Heroku. You need at least 9.2, because we depend on being able to specify a URI to psql, and that was added in 9.2.

  • Mac: use Homebrew: brew install postgres
  • Ubuntu: use Apt: apt-get install postgresql postgresql-contrib libpq-dev

To setup the instance for gratipay's needs run:

sudo -u postgres createuser --superuser $USER
createdb gratipay
createdb gratipay-test

You can speed up the test suite when using a regular HDD by running:

psql -q gratipay-test -c 'alter database "gratipay-test" set synchronous_commit to off'


Once Postgres is set up, run:

make schema

Which populates the database named by DATABASE_URL with the schema from sql/schema.sql.

Example data

The gratipay database created in the last step is empty. To populate it with some fake data, so that more of the site is functional, run this command:

make fake


The Gratipay API is comprised of these four endpoints:

/about/charts.json (source)—public—Returns an array of objects, one per week, showing aggregate numbers over time. The stats page uses this.

/about/paydays.json (source)—public—Returns an array of objects, one per week, showing aggregate numbers over time. The old charts page used to use this.

/about/stats.json (source)—public—Returns an object giving a point-in-time snapshot of Gratipay. The stats page displays the same info.

/~username/public.json (example, source)—public—Returns an object with these keys:

  • "taking"—an estimate of the amount the given participant will take from Teams this week

  • "elsewhere"—participant's connected accounts elsewhere; returns an object with these keys:

    • "bitbucket"—participant's Bitbucket account; possible values are:
      • undefined (key not present)—no Bitbucket account connected
    • "github"—participant's GitHub account; possible values are:
      • undefined (key not present)—no GitHub account connected
    • "twitter"—participant's Twitter account; possible values are:
      • undefined (key not present)—no Twitter account connected
    • "openstreetmap"—participant's OpenStreetMap account; possible values are:
      • undefined (key not present)—no OpenStreetMap account connected

/~username/payment-instructions.json (source)—private—Responds to GET with an array of objects representing your current payment instructions. A payment instruction is created when a ~user instructs Gratipay to make voluntary payments to a Team. Pass a team_slug with GET to fetch payment instruction only for that particular team. POST an array of objects containing team_slug and amount to bulk upsert payment instructions (make sure to set Content-Type to application/json). The amount must be encoded as a string rather than a number. In case the upsert is not successful for any object, there will be an error attribute in the response explaining the error along with the team_slug to identify the object for which the error occurred.

This endpoint requires authentication. Look up your user ID and API key on your account page and pass them using basic auth.

E.g.: Request

curl \
    -u $userid:$api_key \
    -X POST \
    -d '[{"amount": "1.00", "team_slug": "foobar"}]' \
    -H "Content-Type: application/json"


        "amount": "1.00",
        "ctime": "2016-01-30T12:38:00.182230+00:00",
        "due": "0.00",
        "mtime": "2016-02-06T14:37:28.532508+00:00",
        "team_name": "Foobar team",
        "team_slug": "foobar"

API Implementations

Below are some projects that use the Gratipay APIs, that can serve as inspiration for your project!

Renamed to Gratipay

Still Using Gittip

These probably still work, but are using our old name:


Account Elsewhere - An entity's registration on a platform other than Gratipay (e.g., Twitter).

Entity - An entity.

Participant - An entity registered with Gratipay.

User - A person using the Gratipay website. Can be authenticated or anonymous. If authenticated, the user is guaranteed to also be a participant.


Gratipay is dedicated to public domain. See the text of CC0 1.0 Universal dedication in COPYING here.