Integrate Multando in Minutes
Add traffic infraction reporting to your app with our SDKs. Available for Flutter, React Native, iOS, and Android.
Quick Start
Choose your platform and start reporting in 3 steps
npm install @multando/react-native-sdkimport { MultandoProvider, useMultando } from '@multando/react-native-sdk';
// Wrap your app
<MultandoProvider config={{
baseUrl: 'https://api.multando.com/api/v1',
locale: 'en',
}}>
<App />
</MultandoProvider>
// In any component
const { auth, reports } = useMultando();
await auth.login('user@example.com', 'password');API Key Format
Sandbox
mult_test_xxxxxxxxxxxxxxxxProduction
mult_live_xxxxxxxxxxxxxxxxConnect Multando (OAuth)
Let users authorize your app to access their Multando account β no double login
Authorization Flow
Your app redirects to multando.com/oauth/authorize with your client_id, redirect_uri, and requested scopes
User sees the consent screen and taps "Authorize"
Multando redirects to your callback URL with an authorization code
Your backend exchanges the code via POST /api/v1/oauth/token
You receive an access_token and refresh_token to act on behalf of the user
Authorize URL
multando.com/oauth/authorize?client_id=YOUR_API_KEY&redirect_uri=myapp://callback&scope=reports:create,balance:readCode Examples
// Build the authorize URL
final url = client.auth.buildAuthorizeUrl(
redirectUri: 'myapp://multando-callback',
);
await launchUrl(Uri.parse(url));
// After user authorizes, handle the callback
final tokens = await client.auth.exchangeOAuthCode(
code: callbackCode,
redirectUri: 'myapp://multando-callback',
);Redirect URIs
Register your callback URIs for each API key. Only pre-registered URIs are accepted during authorization.
PUT /api/v1/api-keys/{id}/redirect-uris
{"redirect_uris": ["myapp://callback", "https://myapp.com/callback"]}Available Scopes
| Scope | Description |
|---|---|
| reports:create | Create reports on behalf of the user |
| reports:read | Read user's report history |
| infractions:read | List available infraction types |
| users:read | View user profile |
| balance:read | View wallet balance |
/reportsAuthCreate an infraction report/reportsList reports (paginated, filterable)/reports/{id}Get report detail by ID or short_id/reports/by-plate/{plate}Reports by vehicle plate/reports/geojsonPublic GeoJSON FeatureCollection/widget/reports-mapEmbeddable HTML map widget/reports/{id}AuthDelete a pending reportPublic Data API (GeoJSON)
Cities and third parties can consume our verified-reports data in standard GeoJSON format. No authentication required.
Endpoint
https://api.multando.com/api/v1/reports/geojsonQuery Parameters
| Param | Type | Description |
|---|---|---|
| city_id | int | Filter by city ID |
| status | string | Comma-separated statuses (default: approved,community_verified) |
| since | ISO 8601 | ISO 8601 datetime β only newer reports |
| bbox | string | Bounding box: minLon,minLat,maxLon,maxLat |
| limit | int | Max features (1-5000, default 500) |
| api_key | string | Optional API key (header X-API-Key or ?api_key=) |
Fetch with curl
curl 'https://api.multando.com/api/v1/reports/geojson?city_id=1&status=approved,community_verified&limit=500'Embed on your site with Leaflet
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<div id="map" style="height:500px"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
const map = L.map('map').setView([4.711, -74.072], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
fetch('https://api.multando.com/api/v1/reports/geojson?city_id=1')
.then(r => r.json())
.then(data => L.geoJSON(data).addTo(map));
</script>Responses never include vehicle plates or reporter identifiers β safe to embed publicly.
Drop-in map widget with your colors
Add an interactive infraction map to your city portal in 1 line
Embed code
<iframe
src="https://api.multando.com/api/v1/widget/reports-map?tabs=map,leaderboard&default_tab=map&primary_color=e63946&height=560&use_icons=true&lang=en"
width="100%" height="560" frameborder="0" allow="geolocation"></iframe>Configuration options
| Param | Type | Default | Description |
|---|---|---|---|
| city_id | int | β | Filter by city |
| status | string | approved,community_verified | Comma-separated statuses |
| primary_color | hex | e63946 | Accent color (no #) |
| lat | float | 4.7110 | Initial center latitude |
| lon | float | -74.0721 | Initial center longitude |
| zoom | int | 12 | Initial zoom (1-20) |
| height | px | 500 | Map height in pixels |
| show_legend | bool | true | Show status legend |
| lang | es|en | es | UI language (alias of locale) |
| locale | es|en | es | UI locale |
| limit | int | 500 | Max markers (1-5000) |
| cluster | bool | true | Cluster markers |
| use_icons | bool | false | Use Multando hand-pin icons instead of plain dots |
| tabs | string | map | Panels to show: map, leaderboard, or map,leaderboard |
| default_tab | map|leaderboard | map | Tab selected on load (when multiple) |
Example color schemes
Bogota (amber)
?primary_color=f59e0bMedellin (blue)
?primary_color=0066ccCali (red)
?primary_color=e63946Widget shows 'Powered by Multando' β free for authority use.
Backend API Clients
Official clients for server-to-server integration
Python
pip install multandofrom multando import MultandoSyncClient
client = MultandoSyncClient(api_key="mult_live_xxx")
client.login("user@example.com", "password")
reports = client.reports.list()Node.js
npm install @multando/nodeimport { MultandoClient } from '@multando/node';
const client = new MultandoClient({ apiKey: 'mult_live_xxx' });
await client.login('user@example.com', 'password');
const reports = await client.reports.list();Deploy Multando on Your Infrastructure
Run the entire platform on your own servers with Docker. Full control over your data, your rules.
Prerequisites
- Docker & Docker Compose
- An Anthropic API key (for AI chatbot)
- A domain name (optional, for production)
Clone the repository
git clone https://github.com/jeronimotech/multando-backend.git
cd multando-backend
cp .env.example .env
Configure environment
Edit .env with your secrets. Optionally enable federation to connect to the Multando Hub.
# .env
SECRET_KEY=your-secret-key-here
ANTHROPIC_API_KEY=sk-ant-...
# Optional: connect to the Multando Hub
FEDERATION_ENABLED=true
FEDERATION_HUB_URL=https://api.multando.com
FEDERATION_API_KEY=your-hub-key
Start the platform
docker compose -f docker-compose.self-host.yml up -d
This starts PostgreSQL, Redis, MinIO, and the API server. Migrations run automatically on first boot.
Verify it works
Check the health endpoint and open the API documentation.
curl http://localhost:8000/health
# {"status":"healthy","version":"0.1.0"}
# API docs at http://localhost:8000/docs
# Frontend at http://localhost:3000
Frontend (optional)
git clone https://github.com/jeronimotech/multando-frontend.git
cd multando-frontend
echo "NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1" > .env
docker build -t multando-frontend .
docker run -p 3000:3000 multando-frontend
How It Works
Your app integrates via SDK. Reports flow through our API to the community for verification.
Your App
SDK integration
Multando API
Validation + storage
Community
Verification + rewards
Two Environments
Test your integration safely in sandbox before going live
Sandbox
For testing & development
Base URL
https://sandbox-api.multando.com/api/v1API Key Format
mult_test_xxxxxxxxxxxxxxxx- β Free unlimited testing
- β No real tokens or transactions
- β Higher rate limits (300/min)
Production
For live applications
Base URL
https://api.multando.com/api/v1API Key Format
mult_live_xxxxxxxxxxxxxxxx- β Real MULTA token rewards
- β Live data and transactions
- β Standard rate limits (60/min)
β οΈ Keys are environment-locked β Sandbox keys (mult_test_) only work on sandbox-api.multando.com. Production keys (mult_live_) only work on api.multando.com. They cannot be interchanged.
