A barebones, runnable implementation of the Open Charity API Standard (OCAS), built with FastAPI. It's a sibling to the Node.js reference server: same behaviour, same seed data, different language, so you can see the spec is genuinely portable.
It's built for learning and conformance testing. It is not production software: there's no persistence (data lives in memory and resets on restart), no real payment processing, no authentication, and no rate limiting. Think of it as an executable copy of the spec.
Implements the core OCAS endpoints in ocas/server.py:
GET /charity— capability discoveryGET /campaigns,GET /campaigns/{id}GET /funds,GET /funds/{id}POST /donations,GET /donations,GET /donations/{id},POST /donations/{id}/refundPOST /subscriptions,GET /subscriptions,GET /subscriptions/{id},PATCH,DELETEGET /receipts/{id}GET /zakat/calculatorPOST /webhooks,GET /webhooks,DELETE /webhooks/{id}
It enforces the same rules as the Node server, the parts of OCAS that are easy to get wrong:
- Money is integer minor units.
2500means £25.00. Decimals are rejected. - Asnaf allocations must sum to 100. A Zakat donation split across the 8 canonical categories has to add up.
interest_purificationcan never be Zakat. Sendingzakat_metadatawith that type is a422.- Idempotency. Repeating a
POST /donationswith the sameIdempotency-Keyreturns the original donation rather than creating a duplicate. - Referential integrity. Referencing a campaign or fund that doesn't exist is a
422.
It runs in public auth mode, so no credentials are needed.
You need Python 3.10 or newer.
cd ocas-reference-python
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
uvicorn ocas.server:app --reloadThe server starts on http://localhost:8000. Then, in another terminal:
# Discover what the charity supports
curl http://localhost:8000/api/ocas/v1/charity
# Make a Zakat donation split 60/40 across two Asnaf categories
curl -X POST http://localhost:8000/api/ocas/v1/donations \
-H "Content-Type: application/json" \
-d '{
"amount": { "value": 2500, "currency": "GBP" },
"donation_type": "zakat",
"donor": { "first_name": "Aisha", "last_name": "Khan", "email": "aisha@example.com" },
"zakat_metadata": {
"asnaf_allocation": [
{ "asnaf": "fuqara", "percentage": 60 },
{ "asnaf": "masakin", "percentage": 40 }
]
}
}'Because this is built with FastAPI, you also get interactive API docs for free at http://localhost:8000/docs once the server is running. Note these are FastAPI's auto-generated docs describing this server; the canonical OCAS spec lives in ../open-charity-api/.
pip install -r requirements.txt # includes pytest + httpx
pytestThe tests in tests/test_server.py double as a small conformance suite: happy path, validation rules, idempotency, and refunds. They use FastAPI's TestClient, so no running server is needed.
ocas-reference-python/
├── requirements.txt FastAPI, uvicorn, plus pytest + httpx for tests.
├── ocas/
│ ├── server.py All the routes.
│ ├── store.py In-memory data + seed data (Hope Mosque Foundation).
│ └── validation.py The OCAS-specific rules (money, Asnaf, Zakat).
└── tests/
└── test_server.py Conformance-style tests.
This is one implementation of OCAS, alongside the Node.js one. The spec is the source of truth; if any implementation and the spec disagree, the spec wins (and please open an issue). Implementations in other languages — Go, PHP, Ruby, Rust — are very welcome as contributions.
Licensed Apache 2.0, same as the rest of The Foundation.