Skip to main content

Bemba API Reference

The Bemba API is a REST API that allows interaction with all system features.

Base URL​

https://sig.example.com/api

Authentication​

The API uses JSON Web Tokens (JWT) for authentication.

Getting a Token​

curl -X POST https://sig.example.com/api/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "password"}'

Response:

{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
"refresh_token": "abc123...",
"user": {
"id": "0f8fad5b-d9cb-469f-a165-70867728950e",
"email": "user@example.com",
"roles": ["ROLE_USER"],
"nom": "Exemple",
"prenom": "Agent"
}
}

The JWT lasts 1 hour, the refresh token 30 days. If two-factor authentication is enabled, the response carries requires2FA: true and the token is then obtained through POST /api/2fa/verify (see Login).

Login also sets the BEARER, REFRESH_TOKEN (httpOnly) and XSRF-TOKEN cookies. A client relying on these cookies (the browser case) must send the XSRF-TOKEN value back in the X-CSRF-TOKEN header on every POST, PUT, PATCH or DELETE, otherwise the request is refused with 403. A client that only sends the Authorization: Bearer header is not affected.

Current user and permissions​

EndpointDescription
GET /api/meProfile of the logged-in user
GET /api/me/permissionsGranted module.action permission codes (e.g. registre.menages_edit)

Every protected endpoint checks a permission of this kind; returned data is also limited to the user's scope (institution and projects).

Using the Token​

Include the token in the Authorization header:

curl https://sig.example.com/api/menages \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."

Refreshing the Token​

curl -X POST https://sig.example.com/api/token/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "abc123..."}'

The refresh token is renewed on every call (rotation). Logout is done through POST /api/token/invalidate (see Logout).


Response Format​

The API exposes two families of endpoints, with two formats.

Business controllers: { success, data }​

Most endpoints (beneficiaries, transfers, payments, complaints, monitoring and evaluation, assistant…) return:

{
"success": true,
"data": [ { "...": "..." } ],
"pagination": { "page": 1, "limit": 20, "total": 1234, "pages": 62 }
}

pagination only appears on paginated lists (page and limit parameters). On error: { "success": false, "error": "message" } (or message) with the appropriate HTTP code.

API Platform resources: JSON-LD / Hydra​

Reference resources (households, regions, sectors, localities, projects…) follow the Hydra format:

{
"@context": "/api/contexts/Menage",
"@id": "/api/menages",
"@type": "hydra:Collection",
"hydra:totalItems": 1234,
"hydra:member": [ { "@id": "/api/menages/0f8fad5b-…", "@type": "Menage", "codeMenage": "…" } ],
"hydra:view": {
"@id": "/api/menages?page=1",
"@type": "hydra:PartialCollectionView",
"hydra:first": "/api/menages?page=1",
"hydra:last": "/api/menages?page=62",
"hydra:next": "/api/menages?page=2"
}
}

Sending Accept: application/json returns a plain JSON array, without Hydra metadata.

Errors from these resources follow RFC 7807 (application/problem+json):

{
"type": "/errors/404",
"title": "An error occurred",
"status": 404,
"detail": "Not Found"
}

Identifiers are UUIDs.


HTTP Codes​

CodeDescription
200Success
201Resource created
204Success without content (DELETE)
400Invalid request (missing field, value not in list)
401No session: token missing, expired or invalid
403Valid session but missing permission, object outside the user's scope, or missing CSRF header
404Resource not found, including for a malformed (non-UUID) identifier
422Validation error (API Platform resources)
429Too many requests (login, assistant)
500Server error

Pagination​

API Platform resources: page and itemsPerPage parameters. The default size depends on the resource (20 for households, 30 otherwise); itemsPerPage is capped at 200. Some resources accept pagination=false.

Business controllers: page and limit parameters (20 by default), response in the pagination block.

curl "https://sig.example.com/api/menages?page=2&itemsPerPage=50" \
-H "Authorization: Bearer TOKEN"

Filters​

API Platform resources filter on properties, often by relation identifier:

FilterDescriptionExample
region.idFilter by region?region.id=<uuid>
secteur.idFilter by sector?secteur.id=<uuid>
localite.idFilter by locality?localite.id=<uuid>
projet.idFilter by project?projet.id=<uuid>
statutFilter by status?statut=actif
order[champ]Sorting?order[createdAt]=desc

Business controllers use simple parameters specific to each endpoint (search, statut, projet_id, region…): see each endpoint's page.


Main Endpoints​

Authentication​

MethodEndpointDescription
POST/api/loginLogin
POST/api/2fa/verifyTwo-factor authentication code
POST/api/token/refreshRefresh token
POST/api/token/invalidateLogout
GET/api/meCurrent user
GET/api/me/permissionsUser permissions

Households​

MethodEndpointDescription
GET/api/menagesList households
GET/api/menages/\{id\}Household details
POST/api/menagesCreate a household
POST/api/menages/\{id\}/updateUpdate a household (full form)
DELETE/api/menages/\{id\}Delete a household

Beneficiaries​

MethodEndpointDescription
GET/api/beneficiairesList beneficiaries
GET/api/beneficiaires/\{id\}Beneficiary details

Transfers (payment cycles)​

MethodEndpointDescription
GET/api/cyclesList transfers
POST/api/cyclesCreate a transfer
POST/api/cycles/\{id\}/generate-paymentsGenerate payments
POST/api/cycles/\{id\}/soumettreSubmit for validation
POST/api/cycles/\{id\}/validerValidate the next level

Other modules​

PrefixDescription
/api/plaintesGrievance redress mechanism (see Complaints)
/api/suivi-evaluationWork plan, indicators, risks, missions (see Monitoring & Evaluation)
/api/assistantBemba assistant (see Assistant)
/api/photosPhotos served through signed URLs (see Photos)

Code Examples​

JavaScript (Fetch)​

const login = async (email, password) => {
const response = await fetch('https://sig.example.com/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
return response.json();
};

const getMenages = async (token) => {
const response = await fetch('https://sig.example.com/api/menages', {
headers: { 'Authorization': `Bearer ${token}` }
});
return response.json();
};

Python (Requests)​

import requests

# Login
response = requests.post(
'https://sig.example.com/api/login',
json={'email': 'user@example.com', 'password': 'password'}
)
token = response.json()['token']

# Get menages
menages = requests.get(
'https://sig.example.com/api/menages',
headers={'Authorization': f'Bearer {token}'}
).json()

PHP (Guzzle)​

use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'https://sig.example.com/api']);

// Login
$response = $client->post('/api/login', [
'json' => ['email' => 'user@example.com', 'password' => 'password']
]);
$token = json_decode($response->getBody())->token;

// Get menages
$menages = $client->get('/api/menages', [
'headers' => ['Authorization' => "Bearer $token"]
]);