University of Innsbruck x OpenCharities

OpenCharities Student API

A sandbox with fictional data, so your prototype can make a real API call. Everything here is fake and nothing you send is ever stored: a POST returns a realistic object with meta.simulated: true, and the next GET will not contain it.

Authentication

Send your group key in the X-OC-Group-Key header on every request except /v1/health. A missing or wrong key returns 401. CORS is open, so you can call the API from the browser. Keep your key out of public repositories.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/ngos?limit=3"

Responses

// success
{ "data": ..., "meta": { "requestId": "req_...", "simulated": false } }
// lists add meta.nextCursor (null on the last page)
// error
{ "error": { "code": "validation_error", "message": "...", "fields": [{ "field": "amountEur", "message": "..." }] },
  "meta": { "requestId": "req_..." } }

Lists take ?limit= (1 to 100, default 20) and ?cursor= (pass back meta.nextCursor). Quote the requestId when you ask us about a call. Field names are camelCase; IDs look like NGO-001, and created objects get IDs with -SIM- in them.

Endpoints

GET

/v1/health

Liveness check. No key needed.

curl -s "https://sandbox-api.opencharities.com/v1/health"
GET

/v1/initiatives

Fictional fundraising initiatives, each tied to an NGO. Filters: ngoId, status, category.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/initiatives"
GET

/v1/initiatives/INI-001

One initiative.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/initiatives/INI-001"
GET

/v1/ngos

Fictional NGOs with KYB status. Filters: country, kybStatus.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/ngos"
GET

/v1/ngos/NGO-001

One NGO.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/ngos/NGO-001"
GET

/v1/donations?initiativeId=INI-001

Past donations, newest first. Filters: initiativeId, status.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/donations?initiativeId=INI-001"
POST

/v1/donations

Create a simulated donation. Nothing is stored.

curl -s -X POST -H "X-OC-Group-Key: $OC_GROUP_KEY" -H "Content-Type: application/json" \
  -d '{"initiativeId":"INI-001","amountEur":25,"donorName":"Alex","paymentMethod":"ideal"}' \
  "https://sandbox-api.opencharities.com/v1/donations"
GET

/v1/recipients

Recipients by ID only (no real people). Filters: region, cashOutChannel.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/recipients"
GET

/v1/payout-batches

Aid payout batches. Filters: ngoId, status, cashOutChannel.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/payout-batches"
POST

/v1/payout-batches

Plan a simulated payout batch.

curl -s -X POST -H "X-OC-Group-Key: $OC_GROUP_KEY" -H "Content-Type: application/json" \
  -d '{"ngoId":"NGO-001","recipientIds":["REC-001","REC-002"],"amountPerRecipientEur":30,"cashOutChannel":"mobile_money","plannedDate":"2026-12-01"}' \
  "https://sandbox-api.opencharities.com/v1/payout-batches"
POST

/v1/payout-batches/BAT-0002/confirmations

Confirm that a recipient did or did not receive their payout.

curl -s -X POST -H "X-OC-Group-Key: $OC_GROUP_KEY" -H "Content-Type: application/json" \
  -d '{"recipientId":"REC-001","status":"received","confirmedBy":"AGT-001"}' \
  "https://sandbox-api.opencharities.com/v1/payout-batches/BAT-0002/confirmations"
GET

/v1/field-agents

Field agents who capture deliveries offline. Filters: role, region.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/field-agents"
GET

/v1/delivery-events

Offline-captured hand-overs with captured and synced times. Filters: agentId, syncStatus.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/delivery-events"
POST

/v1/proofs

Returns the SHA-256 of the submitted content (or echoes a submitted hash) with a timestamp. Send exactly one of content or hash.

curl -s -X POST -H "X-OC-Group-Key: $OC_GROUP_KEY" -H "Content-Type: application/json" \
  -d '{"content":"20 water kits handed over, countersigned M.A.","deliveryEventId":"EVT-0005"}' \
  "https://sandbox-api.opencharities.com/v1/proofs"
GET

/v1/companies

Fictional companies for employee-driven giving.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/companies"
GET

/v1/giving-rounds

Giving rounds with a shortlist of NGOs, 100 points per employee, quadratic voting. Filters: companyId, status.

curl -s -H "X-OC-Group-Key: $OC_GROUP_KEY" "https://sandbox-api.opencharities.com/v1/giving-rounds"
POST

/v1/giving-rounds/GR-001/votes

Cast a simulated ballot. n votes on one NGO cost n squared points; total must stay at or under 100. Round must be open.

curl -s -X POST -H "X-OC-Group-Key: $OC_GROUP_KEY" -H "Content-Type: application/json" \
  -d '{"employeeId":"emp-42","allocations":[{"ngoId":"NGO-001","votes":6},{"ngoId":"NGO-006","votes":4}]}' \
  "https://sandbox-api.opencharities.com/v1/giving-rounds/GR-001/votes"

Error codes

400validation_error, invalid_json, invalid_limit, invalid_cursor
401unauthorized: missing or invalid key
404not_found
405method_not_allowed
409round_not_open: voting on a closed or upcoming round

Machine-readable contract: openapi.yaml (OpenAPI 3.1).