jamiio API
Build jamiio into your own software. Read and write communities, members, events, votes, funds and maintenance jobs over HTTPS with JSON.
Introduction
The API is HTTP and JSON, with 35 endpoints. Everything the jamiio apps do, you can do — there is no private API behind this one.
- All requests use HTTPS. Plain HTTP is rejected.
- All request and response bodies are JSON.
- Every request must be authenticated. See below.
- Timestamps are ISO 8601 in UTC. Money is an integer in minor units.
Base URL
https://api.jamiio.net/v1
Every path in this document is relative to that base. So
/health means
https://api.jamiio.net/v1/health.
Quick start
Check the service is up. This is the one call that needs no key:
curl https://api.jamiio.net/v1/health
{ "ok": true, "tables": 15 }
Then register a key and use it. Full steps below.
Authentication
There are two ways to call the API. Which one you want depends on whether a person is present.
| Method | Use it when |
|---|---|
| API key | Your system calls jamiio on its own — a sync job, a backend, a report. This is what you want for an integration. |
| Session token | A signed-in person is using your app and acting as themselves. |
A key acts as the person who created it, with the same permissions and no more. If they administer two communities, the key reaches both. If they are an ordinary member, the key is too.
Authentication steps
1. Create a jamiio account
Sign in at the jamiio app and join or start a community. A key can only reach communities its owner belongs to, so this decides what your integration can see.
2. Register a client
Give it a name you will recognise later.
curl -X POST https://api.jamiio.net/v1/clients \
-H 'Authorization: Bearer YOUR_SESSION_TOKEN' \
-H 'content-type: application/json' \
-d '{ "name": "Billing sync", "scopes": ["read", "write"] }'
3. Save the secret
The response contains your credentials:
{
"client": {
"id": "jam_9f3c2a1b7e4d8055",
"name": "Billing sync",
"scopes": ["read", "write"]
},
"secret": "sk_2b91d4ff08c6a37e5401bd9e77aa3c62f0d18e4b96c5a237",
"note": "Copy the secret now — it is not stored and cannot be shown again."
}
The secret is shown once. It is stored only as a hash, so nobody — including us — can recover it. If you lose it, revoke the key and register a new one.
4. Send both headers on every request
curl https://api.jamiio.net/v1/communities?mine=1 \
-H 'x-jamiio-client: jam_9f3c2a1b7e4d8055' \
-H 'x-jamiio-secret: sk_2b91d4ff08c6a37e5401bd9e77aa3c62f0d18e4b96c5a237'
That is the whole of it. There is no token exchange, no refresh, and nothing expires.
Scopes
| Scope | Allows |
|---|---|
read | GET requests. |
write | POST, PUT, PATCH and DELETE as well. |
Ask for read only, unless you need to write. It is the default.
Enforced on every writing method. A read-only key attempting one is
refused with 403 before the request reaches the endpoint —
including POST /clients, so it cannot register itself a
wider key.
Revoking a key
Takes effect immediately. There is no grace period.
curl -X DELETE https://api.jamiio.net/v1/clients \
-H 'x-jamiio-client: jam_9f3c2a1b7e4d8055' \
-H 'x-jamiio-secret: sk_...' \
-d '{ "id": "jam_9f3c2a1b7e4d8055" }'
List your keys with GET /clients. Secrets are never included.
Requests
Send JSON, get JSON.
curl -X POST https://api.jamiio.net/v1/communities \
-H 'x-jamiio-client: jam_...' \
-H 'x-jamiio-secret: sk_...' \
-H 'content-type: application/json' \
-d '{ "name": "Riverside Gardens", "area": "Kileleshwa", "countryCode": "KE", "homes": 60 }'
{
"community": {
"id": "riverside-gardens",
"name": "Riverside Gardens",
"area": "Kileleshwa",
"homes": 60,
"members": 1
}
}
Errors
Every error has the same shape:
{ "error": "That invitation has already been used, or has expired" }
| Code | Meaning | What to do |
|---|---|---|
400 | Missing or malformed field. | Fix the request. |
401 | Missing, wrong or revoked credentials. | Check both headers. |
403 | Not yours. | The key's owner does not have access. |
404 | No such record. | Check the id. |
409 | Exists, but not in a state that allows this. | A spent invite, a closed vote. |
429 | Too many requests. | Wait for Retry-After. |
Branch on the status code. The message is written for people and may change.
Rate limits
Per key, in fixed one-minute windows.
| Requests | Per minute |
|---|---|
/health | 600 |
| Reads | 120 |
| Writes | 30 |
| Votes | 20 |
Every response tells you where you stand:
RateLimit-Limit: 120
RateLimit-Remaining: 117
RateLimit-Reset: 41
Personal data
The API never returns another person's phone number, email, exact location or financial detail. You get a display name and a house number:
{ "name": "Wanjiru K.", "unit": "House 14" }
This applies to your integration too. There is no scope, parameter or account type that lifts it. Build accordingly: if you need to contact a resident, ask them, do not expect the API to hand them over.
Communities
Members and invites
An invite is for one named person, works once, and expires in seven days. It carries a three-word phrase the sender says out loud. A forwarded link shows different words, which is how a recipient knows it was not meant for them.
Events and voting
One home, one vote. Voting again replaces your first vote rather than adding to the count. Tallies are counted from the votes on every read, so they cannot drift.
Money
Amounts are integers in minor units. 2500 means 25.00 where
the currency has two decimal places. Nothing is charged through the API —
it records money that moved elsewhere.