API and integrations
Published reports are available through a JSON API, through Open311 (compatible with GIS such as ArcGIS or QGIS and with maintenance systems), through webhooks and through an embeddable widget.
Principles
- Each site has its own API, at its own address: here
https://scopemy.city. - Only reports published after moderation, and their public fields, are served. On an authority's site: its reports; on scopemy.city: all of them, except those an authority keeps internal.
- Reading is open, without a key. An API key (X-Api-Key header), created by the authority's administrators, raises the rate limit; a write key allows submitting requests through Open311.
- Limit: 120 requests per minute per IP address, 600 per key. Beyond that: a 429 response with a Retry-After header.
- Cursor pagination (pagination.suivant field, Link header). Responses are publicly cached with an ETag: send If-None-Match to get a 304.
- Data under the CC BY 4.0 licence. Open data
OpenAPI 3.1 specification: openapi.yaml · openapi.json
curl -H 'Accept: application/json' 'https://scopemy.city/api/v1/signalements?statut=resolu&limite=20'
JSON API
GET /api/v1/signalements
Paginated list of published reports
| Parameter | In | Description |
|---|---|---|
bbox |
query | Area minLng,minLat,maxLng,maxLat (WGS84). |
categorie |
query | One or more categories (comma-separated codes). |
statut |
query | nouveau, en_cours, resolu or rejete (several, comma-separated). |
depuis |
query | Created on or after this date (YYYY-MM-DD). |
jusqua |
query | Created up to and including this date (YYYY-MM-DD). |
q |
query | Search in title, address, description, reference and labels. |
lang |
query | Language of labels (fr, de, it, en), among the site's languages. |
limite |
query | Reports per page (1 to 100, default 50). |
curseur |
query | Opaque cursor of the next page (pagination.suivant). |
GET /api/v1/signalements/{reference}
One published report, by reference
| Parameter | In | Description |
|---|---|---|
reference * |
path | Reference SC-XXXX-XXXX (or legacy FMC-XXXXXX). |
GET /api/v1/carte
Reports in the visible map area, grouped at low zoom
| Parameter | In | Description |
|---|---|---|
bbox * |
query | Displayed area minLng,minLat,maxLng,maxLat (WGS84). |
zoom |
query | Web Mercator zoom level (0 to 22). |
categorie |
query | One or more categories (comma-separated codes). |
statut |
query | nouveau, en_cours, resolu or rejete (several, comma-separated). |
depuis |
query | Created on or after this date (YYYY-MM-DD). |
jusqua |
query | Created up to and including this date (YYYY-MM-DD). |
q |
query | Search in title, address, description, reference and labels. |
Open311 GeoReport v2
JSON format only. Services are the site's categories, requests are published reports; status is open (new, in progress) or closed (resolved, rejected).
GET /open311/v2/discovery.json
Open311 discovery
GET /open311/v2/services.json
Services (the site's categories)
GET /open311/v2/requests.json
Published requests (Open311 filters)
| Parameter | In | Description |
|---|---|---|
service_request_id |
query | One or more references, comma-separated. |
service_code |
query | Service code (category). |
status |
query | open (new, in progress) or closed (resolved, rejected). |
start_date |
query | ISO 8601 date (day precision). |
end_date |
query | ISO 8601 date (day precision, inclusive). |
page |
query | Page (common extension, from 1). |
page_size |
query | Page size (1 to 100, default 50). |
POST /open311/v2/requests.json
Submit a request (write API key)
GET /open311/v2/requests/{id}.json
One published request
| Parameter | In | Description |
|---|---|---|
id * |
path | Report reference. |
Open data
GET /donnees/signalements.csv
CSV export of published reports (CC BY 4.0)
GET /donnees/signalements.geojson
GeoJSON export of published reports (CC BY 4.0)
GET /donnees/statistiques.json
Public statistics (volume, median delays, resolution rate)
Webhooks
An authority can subscribe an https address to these events (administration, API page). We send it a JSON POST within 5 minutes; a report that is not yet published only includes its reference, category, statuses, position and dates.
| Event | Description |
|---|---|
signalement.cree | Report created (awaiting moderation) |
signalement.publie | Report published |
signalement.statut | Status changed (data.ancien_statut holds the previous one) |
signalement.reponse | Official response added or changed |
signalement.affecte | Assigned to a service or an agent (services portal) |
Each delivery is signed in the X-Scopemy-Signature header: t=timestamp,v1=HMAC-SHA256 of the text “t.body” with your secret. Verify it in constant time and reject timestamps older than 5 minutes. X-Scopemy-Delivery gives a stable identifier: ignore a delivery you already received.
$corps = file_get_contents('php://input');
[$t, $sig] = sscanf($_SERVER['HTTP_X_SCOPEMY_SIGNATURE'] ?? '', 't=%d,v1=%s');
$attendu = hash_hmac('sha256', $t . '.' . $corps, $secret);
if (!$sig || !hash_equals($attendu, $sig) || abs(time() - $t) > 300) {
http_response_code(400); exit;
}
$evenement = json_decode($corps, true); // id, type, tenant, data.signalement
http_response_code(204);
Any 2xx response counts as received. Otherwise we retry up to 8 times, doubling the wait (1 min, 2 min, 4 min…, 6 h at most). Redirects are not followed.
Widget for the municipal website
Paste this code into a page of the municipal website to show the map and the latest reports, in the authority's branding. The site must first be allowed in the administration (API page).
<script src="https://scopemy.city/embed.js" data-vue="carte-liste" data-hauteur="560" async></script>
Options: data-vue (carte-liste, carte or liste), data-hauteur (in pixels, or auto), data-lang (fr, de, it, en). The widget sets no cookies.