/open-company-api

OPENcompany Platform API

Primary LanguageClojureMozilla Public License 2.0MPL-2.0

OPENcompany Platform API

MPL License Build Status Dependency Status Roadmap on Trello

Overview

A lack of transparency results in distrust and a deep sense of insecurity.

-- Dalai Lama

Employees and investors, co-founders and execs, they all want more transparency from their startups, but there's no consensus about what it means to be transparent. OPENcompany is a platform that simplifies how key business information is shared with stakeholders.

When information about growth, finances, ownership and challenges is shared transparently, it inspires trust, new ideas and new levels of stakeholder engagement. OPENcompany makes it easy for founders to engage with employees and investors, creating a sense of ownership and urgency for everyone.

OPENcompany is GitHub for the rest of your company.

To maintain transparency, OPENcompany information is always accessible and easy to find. Being able to search or flip through prior updates empowers everyone. Historical context brings new employees and investors up to speed, refreshes memories, and shows how the company is evolving over time.

Transparency expectations are changing. Startups need to change as well if they are going to attract and retain savvy employees and investors. Just as open source changed the way we build software, transparency changes how we build successful startups with information that is open, interactive, and always accessible. The OPENcompany platform turns transparency into a competitive advantage.

Like the open companies we promote and support, the OPENcompany platform is completely transparent. The company supporting this effort, Transparency, LLC, is an open company. The platform is open source software, and open company data is open data accessible through the platform API.

To get started, head to: OPENcompany

Local Setup

Users of the OPENcompany platform should get started by going to OPENcompany. The following local setup is for developers wanting to work on the platform's API software.

Most of the dependencies are internal, meaning Leiningen will handle getting them for you. There are a few exceptions:

  • Java 8 - a Java 8 JRE is needed to run Clojure
  • Leiningen 2.5.1+ - Clojure's build and dependency management tool
  • RethinkDB v2.2.1+ - a multi-modal (document, key/value, relational) open source NoSQL database

Java

Chances are your system already has Java 8 installed. You can verify this with:

java -version

If you do not have Java 8 download it and follow the installation instructions.

Leiningen

Leiningen is easy to install:

  1. Download the latest lein script from the stable branch.
  2. Place it somewhere that's on your $PATH (env | grep PATH). /usr/local/bin is a good choice if it is on your PATH.
  3. Set it to be executable. chmod 755 /usr/local/bin/lein
  4. Run it: lein This will finish the installation.

Then let Leiningen install the rest of the dependencies:

git clone https://github.com/open-company/open-company-api.git
cd open-company-api
lein deps

RethinkDB

RethinkDB is easy to install with official and community supported packages for most operating systems.

RethinkDB for Mac OS X via Brew

Assuming you are running Mac OS X and are a Homebrew user, use brew to install RethinkDB:

brew update && brew install rethinkdb

Follow the instructions provided by brew to run RethinkDB every time at login:

ln -sfv /usr/local/opt/rethinkdb/*.plist ~/Library/LaunchAgents

And to run RethinkDB now:

launchctl load ~/Library/LaunchAgents/homebrew.mxcl.rethinkdb.plist

Verify you can access the RethinkDB admin console:

open http://localhost:8080/

After installing with brew:

  • Your RethinkDB binary will be at /usr/local/bin/rethinkdb
  • Your RethinkDB data directory will be at /usr/local/var/rethinkdb
  • Your RethinkDB log will be at /usr/local/var/log/rethinkdb/rethinkdb.log
  • Your RethinkDB launchd file will be at ~/Library/LaunchAgents/homebrew.mxcl.rethinkdb.plist
RethinkDB for Mac OS X (Binary Package)

If you don't use brew, there is a binary package available for Mac OS X from the Mac download page.

After downloading the disk image, mounting it (double click) and running the rethinkdb.pkg installer, you need to manually create the data directory:

sudo mkdir -p /Library/RethinkDB
sudo chown <your-own-user-id> /Library/RethinkDB
mkdir /Library/RethinkDB/data

And you will need to manually create the launchd config file to run RethinkDB every time at login. From within this repo run:

cp ./opt/com.rethinkdb.server.plist ~/Library/LaunchAgents/com.rethinkdb.server.plist

And to run RethinkDB now:

launchctl load ~/Library/LaunchAgents/com.rethinkdb.server.plist

Verify you can access the RethinkDB admin console:

open http://localhost:8080/

After installing with the binary package:

  • Your RethinkDB binary will be at /usr/local/bin/rethinkdb
  • Your RethinkDB data directory will be at /Library/RethinkDB/data
  • Your RethinkDB log will be at /var/log/rethinkdb.log
  • Your RethinkDB launchd file will be at ~/Library/LaunchAgents/com.rethinkdb.server.plist
RethinkDB for Linux

If you run Linux on your development environment (good for you, hardcore!) you can get a package for you distribution or compile from source. Details are on the installation page.

RethinkDB for Windows

RethinkDB isn't supported on Windows directly. If you are stuck on Windows, you can run Linux in a virtualized environment to host RethinkDB.

Introduction

You can verify all is well with your RethinkDB instance and get familiar with RethinkDB ReQL query language by using the Data Explorer:

open http://localhost:8080/

Next, you can try some things with Clojure by running the REPL from within this project:

lein repl

Then enter these commands one-by-one, noting the output:

(require '[open-company.db.init :as db])
(require '[open-company.resources.company :as company])
(require '[open-company.resources.section :as section])

;; Create DB and tables and indexes
(db/init)

;; Create some companies

(def author {
  :user-id "slack:123456"
  :name "coyote"
  :real-name "Wile E. Coyote"
  :avatar "http://www.emoticonswallpapers.com/avatar/cartoons/Wiley-Coyote-Dazed.jpg"
  :email "wile.e.coyote@acme.com"
  :owner false
  :admin false
  :org-id "slack:98765"
})

(company/create-company
  {
    :name "Blank Inc."
    :currency "GBP"
  } author)

(company/create-company {
  :name "OPENcompany"
  :slug "open"
  :currency "FKP"
  :finances {
    :title "Finances"
    :data [
      {:period "2015-09" :cash 66981 :revenue 0 :costs 8019}
    ]
  }} author)

(company/create-company
  {
    :name "Buffer"
    :currency "USD"
    :update {
      :title "Founder's Update"
      :body "It's all good!"
    }
    :finances {
      :title "Finances"
      :data [
        {:period "2015-08" :cash 1182329 :revenue 1215 :costs 28019}
        {:period "2015-09" :cash 1209133 :revenue 977 :costs 27155}
      ]
      :notes {
        :body "Good stuff! Revenue is up."
      }
    }
  } author)

;; List companies
(company/list-companies)

;; Get a company
(company/get-company "blank-inc")
(company/get-company "transparency")
(company/get-company "buffer")

;; Create/update a section
(section/put-section "blank-inc" :finances {:data [{:period "2015-09" :cash 66981 :revenue 0 :costs 8019}]} author)
(section/put-section "blank-inc" :finances {:data [
  {:period "2015-09" :cash 66981 :revenue 0 :costs 8019}
  {:period "2015-10" :cash 58987 :revenue 25 :costs 7867}]
  :notes {:body "We got our first customer! Revenue FTW!"}} author)
(section/put-section "blank-inc" :finances {:data [
  {:period "2015-08" :cash 75000 :revenue 0 :costs 6778}
  {:period "2015-09" :cash 66981 :revenue 0 :costs 8019}
  {:period "2015-10" :cash 58987 :revenue 25 :costs 7867}]
  :notes {:body "We got our first customer! Revenue FTW!"}} author)
(section/put-section "blank-inc" :finances {:data [
  {:period "2015-08" :cash 75000 :revenue 0 :costs 6778}
  {:period "2015-09" :cash 66981 :revenue 0 :costs 8019}
  {:period "2015-10" :cash 58987 :revenue 25 :costs 7867}
  {:period "2015-11" :cash 51125 :revenue 50 :costs 7912}]
  :notes {:body "We got our second customer! Revenue FTW!"}} author)

(section/put-section "buffer" :update {:title "Founder's Update" :body "It's all meh."} author)

;; Get a section
(section/get-section "transparency" :finances)
(section/get-section "buffer" :update)
(section/get-section "buffer" :finances)

;; List revisions
(section/list-revisions "transparency" :finances)
(section/list-revisions "buffer" :update)
(section/list-revisions "buffer" :finances)

;; Get revisions
(section/get-revisions "transparency" :finances)
(section/get-revisions "buffer" :update)
(section/get-revisions "buffer" :finances)

;; Delete a company
(company/delete-company "transparency")

;; Cleanup
(company/delete-all-companies!)

Usage

Start a production API server:

lein start!

Or start a development API server:

lein start

Create a company with cURL:

TODO: there is no UI yet to do this so you need to create a company via the REPL or CLI import tool.

List the companies with cURL:

curl -i -X GET \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept-Charset: utf-8" \
http://localhost:3000/companies

Request the company with cURL:

curl -i -X GET \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
http://localhost:3000/companies/buffer

Update a company with cURL:

curl -i -X PATCH \
-d '{"currency": "FKP" }' \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
--header "Content-Type: application/vnd.open-company.company.v1+json" \
http://localhost:3000/companies/buffer

Revise a section for the company with cURL:

curl -i -X PUT \
-d '{"body": "It\u0027s all that and a bag of chips.","title": "Founder\u0027s Update"}' \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.section.v1+json" \
--header "Accept-Charset: utf-8" \
--header "Content-Type: application/vnd.open-company.section.v1+json" \
http://localhost:3000/companies/buffer/update

Reorder a company's sections with cURL:

curl -i -X PATCH \
-d '{"sections": {"progress": ["finances", "growth", "team", "product", "marketing", "customer-service", "help", "update"], "company": ["values", "diversity"]}}' \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
--header "Content-Type: application/vnd.open-company.company.v1+json" \
http://localhost:3000/companies/buffer

Remove a section from a company sections with cURL:

curl -i -X PATCH \
-d '{"sections": {"progress": ["finances", "growth", "team", "product", "customer-service", "help", "update"], "company": ["values", "diversity"]}}' \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
--header "Content-Type: application/vnd.open-company.company.v1+json" \
http://localhost:3000/companies/buffer

Add a section to the company with cURL:

curl -i -X PATCH \
-d '{"sections": {"progress": ["finances", "growth", "team", "product", "fundraising", "customer-service", "help", "update"], "company": ["values", "diversity"]}, "fund-raising": {"title": "Fundraising", "body": "No plans. We have enough monies."}}' \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
--header "Content-Type: application/vnd.open-company.company.v1+json" \
http://localhost:3000/companies/buffer

Delete the company with cURL:

curl -i -X DELETE 
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
http://localhost:3000/companies/open

Then, try (and fail) to get the section and the company with cURL:

curl -i -X GET \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.section.v1+json" \
--header "Accept-Charset: utf-8" \
http://localhost:3000/companies/open/update

curl -i -X GET \
--header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyLWlkIjoiMTIzNDU2IiwibmFtZSI6ImNveW90ZSIsInJlYWwtbmFtZSI6IldpbGUgRS4gQ295b3RlIiwiYXZhdGFyIjoiaHR0cDpcL1wvd3d3LmVtb3RpY29uc3dhbGxwYXBlcnMuY29tXC9hdmF0YXJcL2NhcnRvb25zXC9XaWxleS1Db3lvdGUtRGF6ZWQuanBnIiwiZW1haWwiOiJ3aWxlLmUuY295b3RlQGFjbWUuY29tIiwib3duZXIiOmZhbHNlLCJhZG1pbiI6ZmFsc2UsIm9yZy1pZCI6Ijk4NzY1In0.HwqwEijPYDXTLdnL0peO8_KEtj379s4P5oJyv06yhfU" \
--header "Accept: application/vnd.open-company.company.v1+json" \
--header "Accept-Charset: utf-8" \
http://localhost:3000/companies/open

Import sample data

To import company sample data from an edn file run:

lein run -m open-company.util.sample-data -- ./opt/samples/buffer.edn

use -d to erase the company while importing like this:

lein run -m open-company.util.sample-data -- -d ./opt/samples/buffer.edn

To add all the company sample data in a directory (each file with a .edn extension), run:

lein run -m open-company.util.sample-data -- ./opt/samples/

use -d to erase companies while importing like this:

lein run -m open-company.util.sample-data -- -d ./opt/samples/

To add sample data on a production environment, specify the production database name:

DB_NAME="open_company" lein run -m open-company.util.sample-data -- -d ./opt/samples/buffer.edn

or

DB_NAME="open_company" lein run -m open-company.util.sample-data -- -d ./opt/samples/

Testing

Tests are run in continuous integration of the master and mainline branches on Travis CI:

Build Status

To run the tests locally:

lein test!

Participation

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

License

Distributed under the Mozilla Public License v2.0.

Copyright © 2015-2016 Transparency, LLC