# Login Source: https://docs.wede.pt/api-reference/auth/login Authenticate with email and password to obtain a JWT ## Endpoint ## Request Body ```json theme={null} { "email": "admin@company.com", "password": "your-password" } ``` ## Response ```json theme={null} { "token": "eyJhbGci...", "expires_in": 28800, "user": { "id": "uuid", "email": "admin@company.com", "name": "John Smith", "rbac_level": "company_admin", "demo_mode": false, "verticals": ["healthcare", "emergency"] } } ``` The JWT expires in 8 hours (`expires_in` is in seconds). Include it in subsequent requests as `Authorization: Bearer `. ## Notes * `demo_mode: true` means the user has no tenant associated yet — they see static demo data * `rbac_level` determines what the user can access — see [RBAC](/concepts/security) * `verticals` are the operational verticals the user is configured for # Get Token Source: https://docs.wede.pt/api-reference/auth/token Exchange your API key for a JWT token ## Endpoint ## Request ```json theme={null} { "api_key": "wede_live_YOUR_API_KEY" } ``` ## Response ```json theme={null} { "token": "eyJ...", "expires_at": "2026-05-12T10:36:18.223Z", "tenant_id": "9eb65ffa-...", "tenant_slug": "my-company" } ``` ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/auth/token \ -H "Content-Type: application/json" \ -d '{"api_key": "wede_live_YOUR_KEY"}' ``` # Billing & Usage Source: https://docs.wede.pt/api-reference/billing View plan details, usage consumption and invoice history ## Get Billing Overview Returns the current plan, usage for the current year, channel costs and available plans. ### Response ````json theme={null} Returns the current plan, usage for the current year, channel costs and available plans. ### Response ```json { "tenant_id": "uuid", "country": "PT", "current_plan": { "id": "uuid", "name": "growth", "display_name": "Growth", "max_events_per_year": 1000000, "max_zones": 10, "max_users": 50, "max_webhooks": 20, "sla_uptime_pct": 99.9, "feature_flags": { "emergency_dispatch": true, "sms_fallback": true, "voice_fallback": true, "offline_decision": true }, "pricing": { "price_yearly": 50000, "currency": "EUR" } }, "usage": { "events_this_year": 12400, "events_internet": 12100, "sms_used": 280, "voice_used": 20, "lora_used": 0, "satellite_used": 0, "edge_used": 0, "location_updates_offline": 840, "dispatches_total": 156, "dispatches_offline": 12, "missions_total": 156, "overage_events": 0, "overage_amount_eur": 0 }, "channel_costs": [ { "channel": "sms", "cost_per_unit": 0.04, "currency": "EUR" }, { "channel": "voice", "cost_per_unit": 0.08, "currency": "EUR" } ], "available_plans": [] } ```` ## Plans All Wede plans are **annual** — there are no monthly plans. Pricing is defined per country in the local currency. | Plan | Events/year | Zones | Users | SLA | | ---------------- | ----------- | --------- | --------- | ------ | | Starter | 100,000 | 3 | 5 | 99.5% | | Growth | 1,000,000 | 10 | 50 | 99.9% | | Mission-Critical | Unlimited | Unlimited | Unlimited | 99.99% | ## Billable Operations Every operation debits from the tenant annual plan: | Operation | Billed as | | ----------------------------- | -------------------------- | | Event via internet | 1 event | | Event via structured protocol | 1 event + protocol cost | | Event via voice | 1 event + voice cost | | Dispatch | 1 dispatch | | Mission created | 1 mission | | Location update offline | 1 structured protocol unit | When the plan limit is reached, additional usage is billed at the overage rate defined in `channel_costs`. Tenants with no plan are notified and must upgrade or add credit to continue. *** ## List Invoices Returns Stripe invoices for the authenticated tenant. ### Response ```json theme={null} { "data": [ { "id": "in_xxx", "number": "WEDE-0001", "amount_due": 5000000, "currency": "eur", "status": "paid", "created": 1716800000, "invoice_pdf": "https://...", "hosted_invoice_url": "https://..." } ], "count": 1 } ``` `amount_due` is in the smallest currency unit (cents for EUR). Divide by 100 for the display amount. # Report Connectivity Source: https://docs.wede.pt/api-reference/connectivity/report Report a connectivity state change for a zone ## Endpoint ## Request Body | Field | Type | Required | Description | | ------------ | -------- | -------- | ---------------------------- | | zone\_id | string | Yes | Zone code | | state | string | Yes | New connectivity state | | detected\_at | datetime | Yes | When the change was detected | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/connectivity/report \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "zone_id": "zone_lisbon_central", "state": "degraded", "detected_at": "2026-05-13T09:00:00Z" }' ``` # Connectivity Status Source: https://docs.wede.pt/api-reference/connectivity/status Get current connectivity status for all zones ## Endpoint ## Example ```bash theme={null} curl https://api.wede.pt/v1/connectivity/status \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response ```json theme={null} { "zones": [ { "zone_code": "zone_lisbon_central", "state": "online", "fallback_channel": "none", "incident_active": false, "last_updated": "2026-05-13T09:00:00Z" } ], "as_of": "2026-05-13T09:00:00Z" } ``` # Create Event Source: https://docs.wede.pt/api-reference/events/create Send a new event into the Wede platform ## Endpoint ## Request Body | Field | Type | Required | Description | | ---------------- | ------ | -------- | -------------------------------- | | type | string | Yes | Event type | | priority | string | Yes | critical, high, normal, low | | vertical | string | Yes | healthcare, banking, logistics | | idempotency\_key | string | Yes | Unique key to prevent duplicates | | payload | object | No | Opaque payload | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "EMERGENCY", "priority": "critical", "vertical": "healthcare", "idempotency_key": "evt-001", "payload": {"patient_id": "PT-001"} }' ``` ## Response ```json theme={null} { "event_id": "0ee3dfbe-...", "status": "pending", "channel_selected": "rest_full", "created_at": "2026-05-12T10:00:00Z" } ``` # List Events Source: https://docs.wede.pt/api-reference/events/list Retrieve events for your tenant ## Endpoint ## Query Parameters | Parameter | Type | Description | | --------- | ------- | -------------------------------------- | | limit | integer | Number of events (default 50, max 200) | | status | string | Filter by status | | priority | string | Filter by priority | | vertical | string | Filter by vertical | ## Example ```bash theme={null} curl "https://api.wede.pt/v1/events?limit=25&priority=critical" \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response ```json theme={null} { "data": [], "total_count": 142, "limit": 25 } ``` # API Reference Source: https://docs.wede.pt/api-reference/introduction Complete reference for the Wede REST API - offline-first event delivery ## Base URL All API requests are made to: ``` https://api.wede.pt ``` All endpoints are prefixed with `/v1/`. The API is hosted in Europe (GCP europe-west1) with global reach via Cloudflare. ## Authentication All requests require authentication. Wede supports two methods: **API Key** - for server-to-server integrations: ```bash theme={null} curl https://api.wede.pt/v1/events \ -H "X-Wede-API-Key: wede_live_YOUR_KEY" ``` **JWT Token** - for user sessions (obtained via `/v1/auth/login`): ```bash theme={null} curl https://api.wede.pt/v1/events \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` Your API key is available in the [Dashboard](https://app.wede.pt/dashboard/settings). ## Response Format All responses are JSON. Every response includes a `request_id` for support tracing. **Success:** ```json theme={null} { "event_id": "0ee3dfbe-...", "status": "pending", "channel_selected": "rest_full" } ``` **Error:** ```json theme={null} { "error": "validation_error", "message": "Field 'priority' is required", "request_id": "req-abc123" } ``` ## Rate Limiting Rate limits are applied per tenant per minute based on your plan: | Plan | Limit | | ---------------- | ------------- | | Starter | 500 req/min | | Core | 1,000 req/min | | Mission-Critical | Unlimited | Rate limit headers are included in every response: | Header | Description | | ----------------------- | ------------------------------- | | `x-ratelimit-limit` | Requests allowed per minute | | `x-ratelimit-remaining` | Remaining requests this window | | `x-ratelimit-reset` | UTC timestamp when limit resets | ## Idempotency All write operations accept an `idempotency_key`. Use this to safely retry requests without creating duplicates - Wede guarantees exactly-once delivery per key. ## Offline Behaviour When connectivity is unavailable, Wede automatically queues events and delivers them when connectivity is restored. The `channel_selected` field in the response indicates the delivery path used: | Channel | Meaning | | ---------------- | ------------------------------------------ | | `rest_full` | Delivered via HTTPS | | `sms` | Delivered via structured fallback protocol | | `queued_offline` | Queued for delivery on reconnection | Your integration does not need to handle channel selection - Wede routes transparently. # Missions Source: https://docs.wede.pt/api-reference/missions Create and manage operational missions assigned to teams ## Overview A mission is created when a team is dispatched to an event. It tracks the full lifecycle of the field response — from dispatch to completion — and provides the feedback channel for field operators. Missions are the operational record of Wede. They are immutable once completed and form part of the audit trail. *** ## List Missions `GET /v1/missions` Requires `missions:view` permission. ### Query Parameters | Parameter | Type | Description | | ----------- | ------- | -------------------------------------- | | `status` | string | Filter by status (see lifecycle below) | | `team_id` | string | Filter by team | | `member_id` | string | Filter by assigned member | | `limit` | integer | Max results (default 50) | ### Response ```json theme={null} { "data": [ { "id": "uuid", "event_id": "uuid", "team_id": "uuid", "status": "ON_ROUTE", "channel_used": "internet", "vertical": "healthcare", "priority": "high", "notes": "Patient is conscious, use south entrance", "event_lat": 38.7169, "event_lng": -9.1395, "dispatched_at": "2026-06-09T18:00:00Z", "ack_at": "2026-06-09T18:01:30Z", "on_route_at": "2026-06-09T18:02:00Z", "on_site_at": null, "completed_at": null, "failed_at": null, "feedback": null, "created_at": "2026-06-09T18:00:00Z", "updated_at": "2026-06-09T18:02:00Z" } ], "count": 1 } ``` *** ## Get Mission `GET /v1/missions/:id` Requires `missions:view` permission. *** ## Update Mission Status `PATCH /v1/missions/:id/status` Requires `missions:manage` **or** `missions:receive` permission. Field operators use `missions:receive`. Supervisors and admins use `missions:manage`. ### Request Body ```json theme={null} { "status": "ON_SITE", "feedback": { "patient_condition": "stable", "observations": "Patient responsive, BP 120/80" } } ``` | Field | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------------- | | `status` | string | Yes | Next status in lifecycle | | `feedback` | object | No | Opaque structured feedback (parser-defined) | ### Mission Lifecycle Missions follow a strict forward-only progression: | Status | Description | Who sets it | | ----------- | ------------------------------ | ---------------------------- | | `CREATED` | Mission created, team notified | System (on dispatch) | | `SENT` | Notification delivered | System (delivery engine) | | `ACK` | Team acknowledged the mission | Field operator | | `ON_ROUTE` | Team is travelling to location | Field operator | | `ON_SITE` | Team has arrived | Field operator | | `COMPLETED` | Mission closed successfully | Field operator or supervisor | | `FAILED` | Mission could not be completed | Field operator or supervisor | When a mission reaches `COMPLETED` or `FAILED`: * The assigned team is automatically returned to `available` status * The originating event is closed ### Webhooks Status updates fire the `mission.status_updated` webhook: ```json theme={null} { "event": "mission.status_updated", "payload": { "mission_id": "uuid", "status": "ON_SITE", "feedback": {} } } ``` *** ## Backup Dispatch To dispatch a second team to an active mission (reinforcement), use the standard dispatch endpoint with the same `event_id`: `POST /v1/teams/dispatch` ```json theme={null} { "event_id": "uuid-of-original-event", "team_id": "uuid-of-backup-team", "notes": "Backup team — reinforcement requested by field operator", "event_lat": 38.7169, "event_lng": -9.1395 } ``` This creates a new mission for the backup team while the original mission continues. Both missions are tracked independently. ### SDK Method ```typescript theme={null} await client.requestBackup({ mission_id: currentMission.id, event_id: currentMission.event_id, event_lat: currentLocation.lat, event_lng: currentLocation.lng }) ``` # Register Source: https://docs.wede.pt/api-reference/onboarding/register Create a new wede account — starts in demo mode ## Endpoint ## No authentication required This endpoint is public. No API key needed. ## Request Body | Field | Type | Required | Description | | ----------- | ------ | -------- | ----------------------------------------------------------------------------------------------- | | `name` | string | Yes | Full name | | `email` | string | Yes | Work email address | | `password` | string | Yes | Minimum 8 characters | | `country` | string | Yes | ISO 3166-1 alpha-2 country code (e.g. `PT`, `AE`, `NG`) | | `verticals` | array | No | Areas of interest: `healthcare`, `banking`, `telecom`, `logistics`, `emergency`, `gov`, `other` | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/onboarding/register \ -H "Content-Type: application/json" \ -d '{ "name": "Jane Smith", "email": "jane@hospital.org", "password": "SecurePass123", "country": "NG", "verticals": ["healthcare", "emergency"] }' ``` ## Response ```json theme={null} { "status": "pending_verification", "message": "Account created. Check your email to activate your account." } ``` After activation, the account starts in **demo mode** with access to MedCore International sample data. Full access is granted once the account is associated with an organisation by a wede administrator. # Verify Email Source: https://docs.wede.pt/api-reference/onboarding/verify Activate a registered account using the email verification token ## Endpoint ## No authentication required ## Request Body | Field | Type | Required | Description | | ------- | ------ | -------- | ------------------------------------ | | `token` | string | Yes | 64-character token received by email | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/onboarding/verify \ -H "Content-Type: application/json" \ -d '{ "token": "your-64-char-token-here" }' ``` ## Response ```json theme={null} { "status": "active", "message": "Account activated. You can now sign in." } ``` ## Error codes | Status | Code | Description | | ------ | --------------- | ------------------------- | | 404 | `invalid_token` | Token not found | | 409 | `token_used` | Account already activated | | 410 | `token_expired` | Token expired (24h limit) | # Create Parser Source: https://docs.wede.pt/api-reference/parsers/create Creates a new parser for a vertical. A new version is automatically assigned. ## Endpoint POST /v1/parsers ## Authentication Requires `parsers:write` permission. ## Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------------------------------------------------------------ | | `vertical` | string | Yes | Target vertical: `healthcare`, `banking`, `emergency`, `logistics`, `telecom`, `gov` | | `name` | string | Yes | Human-readable name | | `description` | string | No | Optional description | | `schema` | array | Yes | Array of field definitions (max 50) | ### Field definition | Field | Type | Required | Description | | ----------------- | ------- | -------- | ---------------------------------------------------------------------------------------- | | `id` | string | Yes | Unique field identifier | | `name` | string | Yes | Field name | | `sms_code` | string | Yes | Short code for structured protocol encoding (max 8 chars) | | `type` | string | Yes | string, number, boolean, gps, text, timestamp, enum, phone, email, address, hardware\_id | | `required` | boolean | Yes | Whether the field is mandatory | | `enabled` | boolean | Yes | Whether the field is active | | `offline_capable` | boolean | Yes | Whether the field is transmitted via the offline structured protocol | | `section` | string | Yes | core, location, human, hardware, team, custom | | `max_bytes` | number | Yes | Maximum bytes for structured protocol encoding (1-160) | | `enum_values` | array | No | Required when type is enum | | `legal` | boolean | No | Marks the field as containing PII | ## Response Returns the created parser with id, version and created\_at. # List Parsers Source: https://docs.wede.pt/api-reference/parsers/list Returns all parsers configured for the authenticated tenant and vertical ## Endpoint ## Authentication Requires a valid JWT or API key with `parsers:read` permission. | Role | Access | | ----------------------------------------------------------------------------- | ----------------------------------------- | | `wede_global_admin`, `wede_tech_ops` | All parsers across all tenants | | `country_admin` | Parsers for tenants in assigned countries | | `company_admin`, `company_tech`, `operational_supervisor`, `corporate_client` | Own tenant parsers only | ## Response ```json theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "tenant_id": "tenant-uuid", "vertical": "logistics", "version": 1, "name": "Logistics v1", "is_active": true, "created_at": "2026-05-19T14:00:00Z" } ], "count": 1 } ``` # Sync Batch Source: https://docs.wede.pt/api-reference/sync/batch Submit a batch of offline-captured events for processing ## Endpoint ## Authentication Requires a valid API key with `sync:write` permission. ## Request Body | Field | Type | Required | Description | | ------------- | ------ | -------- | ----------------------------------- | | `events` | array | Yes | Array of events captured offline | | `device_id` | string | No | Device identifier for correlation | | `captured_at` | string | Yes | ISO 8601 timestamp of batch capture | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/sync/batch \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "events": [ { "type": "PAYMENT", "idempotency_key": "device-001-1716123456789", "vertical": "banking", "payload": { "amount": 150.00, "currency": "EUR" } } ], "device_id": "device-001", "captured_at": "2026-05-20T10:00:00Z" }' ``` ## Response ```json theme={null} { "accepted": 1, "rejected": 0, "batch_id": "batch-uuid" } ``` # Sync Status Source: https://docs.wede.pt/api-reference/sync/status Check the processing status of a sync batch ## Endpoint ## Authentication Requires a valid API key with `sync:read` permission. ## Query Parameters | Parameter | Type | Required | Description | | ---------- | ------ | -------- | --------------------------------- | | `batch_id` | string | Yes | Batch ID returned from sync/batch | ## Example ```bash theme={null} curl "https://api.wede.pt/v1/sync/status?batch_id=batch-uuid" \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response ```json theme={null} { "batch_id": "batch-uuid", "status": "processed", "accepted": 1, "rejected": 0, "processed_at": "2026-05-20T10:00:05Z" } ``` # Dispatch Team Source: https://docs.wede.pt/api-reference/teams/dispatch Assign a team to an event ## POST /v1/teams/dispatch Requires `dispatch:assign` permission. Dispatching a team creates a mission, sets the team status to `on_mission`, fires the `team.dispatched` webhook, and records a billable operation. ### Request Body | Field | Type | Required | Description | | ----------- | ------ | -------- | ------------------------------------------- | | `event_id` | string | Yes | ID of the event to assign | | `team_id` | string | Yes | ID of the team to dispatch | | `notes` | string | No | Optional dispatch notes visible to the team | | `event_lat` | number | No | Event latitude (improves route display) | | `event_lng` | number | No | Event longitude (improves route display) | ### Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/teams/dispatch \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event_id": "fbea1e0d-8f6b-42f5-bf9b-58fe77430f53", "team_id": "259edc6e-95f3-42ba-bac5-263cfe51ebc0", "notes": "Patient is conscious, use south entrance", "event_lat": 38.7169, "event_lng": -9.1395 }' ``` ### Response ```json theme={null} { "id": "7d154b16-c8ae-4da7-a949-5a97793c667e", "tenant_id": "9c145f7e-83be-4039-8e9c-650796acd3ee", "event_id": "fbea1e0d-8f6b-42f5-bf9b-58fe77430f53", "team_id": "259edc6e-95f3-42ba-bac5-263cfe51ebc0", "dispatched_by": "327739d2-79b6-4e10-8699-a1393e70dbb8", "dispatched_at": "2026-06-09T18:42:45.823Z", "notes": "Patient is conscious, use south entrance" } ``` Dispatching a team automatically sets its status to `on_mission` and creates a mission record. The mission is closed (and the team returned to `available`) when the mission status reaches `COMPLETED` or `FAILED`. *** ## Auto-Dispatch When auto-dispatch is enabled for a tenant, the system automatically dispatches the highest-scored available team when an event arrives — without manual intervention. ### Configure Auto-Dispatch `PATCH /v1/tenant/dispatch-settings` ```json theme={null} { "dispatch_mode": true, "dispatch_threshold": 0.20, "reinforcement_timeout_min": 10 } ``` | Field | Type | Description | | --------------------------- | ------------ | ------------------------------------------------ | | `dispatch_mode` | boolean | Enable or disable auto-dispatch | | `dispatch_threshold` | number (0–1) | Minimum score required for auto-dispatch | | `reinforcement_timeout_min` | integer | Minutes before auto-reinforcement (0 = disabled) | ### Threshold Values | Threshold | Value | Behaviour | | --------- | ------ | ---------------------------- | | Low | `0.10` | Dispatch any available team | | Medium | `0.20` | Team must be well positioned | | High | `0.40` | Only the best-matched team | When no team meets the threshold, the response includes `requires_manual: true` and the supervisor is alerted. ### Auto-Reinforcement If a dispatched team does not acknowledge (`ACK`) a mission within `reinforcement_timeout_min` minutes, the system automatically dispatches the next best available team. Set to `0` to disable. *** ## Manual Override Supervisors can always override auto-dispatch and manually select any available team from the Dispatch Console, regardless of score. *** ## SDK ```typescript theme={null} // Direct dispatch await client.dispatch({ event_id: 'uuid', team_id: 'uuid', event_lat: 38.7169, event_lng: -9.1395, notes: 'Optional notes' }) // Update dispatch settings await client.updateDispatchSettings({ dispatch_mode: true, dispatch_threshold: 0.20, reinforcement_timeout_min: 10 }) // Request backup for active mission await client.requestBackup({ mission_id: 'uuid', event_id: 'uuid', event_lat: 38.7169, event_lng: -9.1395 }) ``` # Team Equipment Source: https://docs.wede.pt/api-reference/teams/equipment Manage equipment assigned to a team ## List Equipment ### Response ```json theme={null} { "data": [ { "id": "uuid", "code": "AED", "name": "Automated External Defibrillator", "status": "operational", "notes": "Checked 2026-05-01", "created_at": "2026-05-01T00:00:00Z" } ] } ``` *** ## Add Equipment Requires `teams:manage` permission. ### Request Body ```json theme={null} { "code": "AED", "name": "Automated External Defibrillator", "status": "operational", "notes": "Optional notes" } ``` | Field | Type | Required | Description | | -------- | ------ | -------- | -------------------------------------------------------------------------- | | `code` | string | Yes | Short equipment code — used in score engine matching | | `name` | string | Yes | Full equipment name | | `status` | string | No | `operational`, `maintenance`, `out_of_service` — defaults to `operational` | | `notes` | string | No | Optional notes | Only equipment with `status: operational` is considered by the score engine when matching against `required_equipment`. *** ## Update Equipment Requires `teams:manage` permission. # List Teams Source: https://docs.wede.pt/api-reference/teams/list Returns all teams configured for the authenticated tenant ## Endpoint ## Authentication Requires a valid API key with `dispatch:view` permission. ## Response ```json theme={null} { "data": [ { "id": "...", "name": "Alpha Medical", "type": "ADVANCED_LIFE_SUPPORT", "vertical": "healthcare", "equipment": ["AED", "VENTILATOR", "STRETCHER"], "status": "available", "members": [ { "id": "...", "name": "Dr. Ana Costa", "role": "PHYSICIAN", "status": "available", "lat": 38.7, "lng": -9.1, "last_seen": "2026-05-14T21:00:00Z" } ], "created_at": "2026-05-01T00:00:00Z", "updated_at": "2026-05-14T20:00:00Z" } ], "count": 1 } ``` # Location Config Source: https://docs.wede.pt/api-reference/teams/location-config Configure GPS tracking intervals for online and offline modes ## Get Location Config Returns the location tracking intervals configured for the authenticated tenant. ### Response ```json theme={null} { "online_interval_sec": 60, "offline_interval_sec": 300 } ``` *** ## Update Location Config Requires `company_admin` or `company_tech` role. ### Request Body ```json theme={null} { "online_interval_sec": 60, "offline_interval_sec": 300 } ``` | Field | Type | Description | | ---------------------- | ------- | -------------------------------------------------------------------------------- | | `online_interval_sec` | integer | GPS update interval when device has internet — minimum 30s | | `offline_interval_sec` | integer | GPS update interval when device is offline via structured protocol — minimum 60s | ## How it works The SDK reads this configuration on login and applies it to the background location tracker. * **Online mode** — GPS sent via REST API at `online_interval_sec` intervals * **Offline mode** — GPS encoded in a structured protocol payload at `offline_interval_sec` intervals, queued and sent when connectivity returns Offline location updates are recorded as billable operations and debited from the tenant plan. # Team Members Source: https://docs.wede.pt/api-reference/teams/members Add, remove and update the status of team members ## Add Member Requires `teams:manage` permission. ### Request Body ```json theme={null} { "name": "Dr. Ana Costa", "role": "PHYSICIAN", "status": "available", "user_id": "uuid" } ``` | Field | Type | Required | Description | | --------- | ------ | -------- | ------------------------------------------------------------------ | | `name` | string | Yes | Member display name | | `role` | string | Yes | Role within the team | | `status` | string | No | `available`, `on_mission`, `offline` — defaults to `available` | | `user_id` | string | No | Link to an existing platform user for GPS tracking and audit trail | When the team has a zone associated, the member is initialised with the zone center coordinates as their starting position. ### Response ```json theme={null} { "id": "uuid", "team_id": "uuid", "name": "Dr. Ana Costa", "role": "PHYSICIAN", "status": "available", "lat": 38.716900, "lng": -9.139500, "last_seen": "2026-05-27T10:00:00Z" } ``` *** ## Update Member Status ### Request Body ```json theme={null} { "status": "on_mission" } ``` *** ## Update Member Location Used by the SDK to send GPS coordinates periodically. Intervals are configured per tenant via the location config endpoint. ### Request Body ```json theme={null} { "lat": 38.7169, "lng": -9.1395 } ``` Include the header `X-Wede-Channel: sms` when the update is sent via the structured fallback protocol — this is recorded for billing purposes. *** ## Remove Member Requires `teams:manage` permission. # Dispatch Score Source: https://docs.wede.pt/api-reference/teams/score Score and rank available teams for a given event using the proximity engine ## Endpoint ## Authentication Requires a valid JWT with `dispatch:assign` permission. ## Request Body ```json theme={null} { "lat": 38.7169, "lng": -9.1395, "vertical": "healthcare", "event_type": "CARDIAC", "priority": "P1_CRITICAL", "required_equipment": ["AED", "VENTILATOR"] } ``` | Field | Type | Required | Description | | -------------------- | --------- | -------- | ------------------------------------------------- | | `lat` | number | Yes | Event latitude | | `lng` | number | Yes | Event longitude | | `vertical` | string | No | Event vertical — filters by capability | | `event_type` | string | No | Specific event type within the vertical | | `priority` | string | No | Severity — `P1_CRITICAL`, `HIGH`, `MEDIUM`, `LOW` | | `required_equipment` | string\[] | No | Equipment codes required for this event | ## Response ```json theme={null} { "scored": [ { "team_id": "uuid", "team_name": "Alpha Medical", "status": "available", "vertical": "healthcare", "distance_km": 2.4, "eta_min": 4, "equipment_match": 0.95, "member_availability": 1.0, "score": 0.08, "recommended": true, "channel": "internet", "position": { "lat": 38.73, "lng": -9.15, "source": "gps", "last_seen": "2026-05-27T10:00:00Z" } } ], "count": 3 } ``` ## Score Algorithm The score engine runs identically on the API (online) and SDK (offline). Lower score is better. | Component | Description | | ------------------ | ------------------------------------------------------- | | `travel_score` | Haversine distance normalised to 30 min max | | `capability_score` | Equipment and vertical match — lower is better match | | `member_score` | Member availability ratio — lower is more available | | `load_penalty` | 0.5 if team is `on_mission`, 0 otherwise | | `geofence_penalty` | 0.2 if event is outside team zone boundary, 0 otherwise | ## Position Sources | Source | Description | | --------- | ------------------------------------------------------------- | | `gps` | Real GPS from a team member, updated within 10 minutes | | `zone` | Zone center coordinates — used when no fresh GPS is available | | `unknown` | No position data — team is still scored but distance is 0 | ## Offline Compatibility This algorithm runs identically on the SDK without a server connection. When offline, the SDK uses the last known member positions and zone boundaries stored locally. # Team Verticals & Capabilities Source: https://docs.wede.pt/api-reference/teams/verticals Configure which verticals and event types a team can respond to ## List Team Verticals ### Response ```json theme={null} { "data": [ { "id": "uuid", "vertical": "healthcare", "event_types": ["CARDIAC", "TRAUMA", "RESPIRATORY"], "parser_id": "uuid" } ] } ``` *** ## Add Vertical Requires `teams:manage` permission. ### Request Body ```json theme={null} { "vertical": "healthcare", "event_types": ["CARDIAC", "TRAUMA", "RESPIRATORY"], "parser_id": "uuid" } ``` | Field | Type | Required | Description | | ------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------ | | `vertical` | string | Yes | The vertical this team covers — `healthcare`, `emergency`, `banking`, `telecom`, `delivery`, `gov`, `energy` | | `event_types` | string\[] | No | Specific event types within the vertical the team can handle | | `parser_id` | string | No | Parser to use for events in this vertical | The score engine uses this configuration to determine capability match. A team that does not list the event vertical gets a capability penalty. *** ## Update Vertical ### Request Body ```json theme={null} { "event_types": ["CARDIAC", "TRAUMA"], "parser_id": "uuid" } ``` *** ## Remove Vertical Requires `teams:manage` permission. # Tenant Profile Source: https://docs.wede.pt/api-reference/tenant/me Get your tenant configuration ## GET /v1/tenant/me Returns the full configuration for the authenticated tenant. Requires authentication (JWT or API key). ### Example ```bash theme={null} curl https://api.wede.pt/v1/tenant/me \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ### Response ```json theme={null} { "id": "9c145f7e-83be-4039-8e9c-650796acd3ee", "name": "Hospital Lisboa", "slug": "hospital-lisboa", "email": "admin@hospital-lisboa.pt", "license_type": "saas_api", "status": "active", "country": "PT", "verticals": ["healthcare", "emergency"], "dispatch_threshold": 0.20, "reinforcement_timeout_min": 10, "feature_flags": { "dispatch_mode": true }, "sla_target_uptime_pct": 99.9, "created_at": "2026-01-15T10:00:00Z", "updated_at": "2026-06-09T18:00:00Z" } ``` ### Response Fields | Field | Type | Description | | ----------------------------- | --------- | ------------------------------------------------ | | `id` | string | Tenant UUID | | `name` | string | Organisation name | | `slug` | string | URL-safe identifier | | `country` | string | ISO 3166-1 alpha-2 country code | | `verticals` | string\[] | Active operational verticals | | `dispatch_threshold` | number | Minimum score for auto-dispatch (0–1) | | `reinforcement_timeout_min` | integer | Minutes before auto-reinforcement (0 = disabled) | | `feature_flags.dispatch_mode` | boolean | Auto-dispatch enabled | | `status` | string | `active`, `suspended`, `inactive` | *** ## PATCH /v1/tenant/dispatch-settings Configure auto-dispatch behaviour for the tenant. Requires `company_admin` or `company_tech` role. ### Request Body ```json theme={null} { "dispatch_mode": true, "dispatch_threshold": 0.20, "reinforcement_timeout_min": 10 } ``` | Field | Type | Description | | --------------------------- | ------------ | ---------------------------------------------------------------------- | | `dispatch_mode` | boolean | Enable or disable auto-dispatch | | `dispatch_threshold` | number (0–1) | Minimum score for auto-dispatch | | `reinforcement_timeout_min` | integer | Minutes before backup auto-dispatch if team doesn't ACK (0 = disabled) | ### Threshold Reference | Level | Value | Behaviour | | ------ | ------ | ---------------------------- | | Low | `0.10` | Dispatch any available team | | Medium | `0.20` | Team must be well positioned | | High | `0.40` | Only the best-matched team | ### Response ```json theme={null} { "dispatch_mode": true, "dispatch_threshold": 0.20, "reinforcement_timeout_min": 10 } ``` ### SDK ```typescript theme={null} // Get tenant info const tenant = await client.getTenantInfo() console.log(tenant.data.verticals) // ['healthcare', 'emergency'] console.log(tenant.data.dispatch_threshold) // 0.20 // Update dispatch settings await client.updateDispatchSettings({ dispatch_mode: true, dispatch_threshold: 0.20, reinforcement_timeout_min: 10 }) ``` # Usage Metrics Source: https://docs.wede.pt/api-reference/tenant/usage Get consumption metrics for your tenant ## Endpoint ## Query Parameters | Parameter | Type | Required | Description | | ----------- | -------- | -------- | ------------------------------------- | | from | datetime | Yes | Start of period (ISO 8601) | | to | datetime | Yes | End of period (ISO 8601) | | granularity | string | No | hour, day, week, month (default: day) | ## Example ```bash theme={null} curl "https://api.wede.pt/v1/tenant/usage?from=2026-05-01T00:00:00Z&to=2026-05-13T00:00:00Z" \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` # Create Webhook Source: https://docs.wede.pt/api-reference/webhooks/create Register a new webhook endpoint ## Endpoint ## Request Body | Field | Type | Required | Description | | ------ | ------ | -------- | -------------------------------------- | | url | string | Yes | HTTPS endpoint to receive events | | events | array | No | Event types to subscribe (empty = all) | ## Example ```bash theme={null} curl -X POST https://api.wede.pt/v1/webhooks \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourapp.com/webhooks/wede", "events": ["EMERGENCY", "DISPATCH"] }' ``` # Delete Webhook Source: https://docs.wede.pt/api-reference/webhooks/delete Remove a webhook ## Endpoint ## Example ```bash theme={null} curl -X DELETE https://api.wede.pt/v1/webhooks/wh-abc123 \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` Returns `204 No Content` on success. # List Webhooks Source: https://docs.wede.pt/api-reference/webhooks/list Get all webhooks configured for your tenant ## Endpoint ## Example ```bash theme={null} curl https://api.wede.pt/v1/webhooks \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response ```json theme={null} { "webhooks": [ { "id": "wh-abc123", "url": "https://yourapp.com/webhooks/wede", "events": ["EMERGENCY"], "created_at": "2026-05-01T00:00:00Z" } ], "total": 1 } ``` # Zone Detail Source: https://docs.wede.pt/api-reference/zones/detail Get details for a specific zone including boundary polygon ## Endpoint ## Response ```json theme={null} { "id": "uuid", "zone_code": "zone_hospital_lisboa", "name": "Hospital Lisboa", "country": "PT", "region": "Lisboa", "lat_center": "38.716900", "lng_center": "-9.139500", "boundary": [ { "lat": 38.72, "lng": -9.14 }, { "lat": 38.71, "lng": -9.13 }, { "lat": 38.70, "lng": -9.15 } ], "verticals_active": ["healthcare"], "connectivity_state": "online", "incident_active": false, "last_state_change": "2026-05-27T10:00:00Z", "created_at": "2026-05-01T00:00:00Z" } ``` The `boundary` field contains the polygon coordinates used by the score engine for geofencing. It is `null` if no boundary has been defined for this zone. # List Zones Source: https://docs.wede.pt/api-reference/zones/list Get all zones configured for your tenant ## Endpoint ## Example ```bash theme={null} curl https://api.wede.pt/v1/tenant/zones \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response ```json theme={null} { "zones": [ { "zone_code": "zone_lisbon_central", "name": "Lisboa Central", "country": "PT", "connectivity_state": "online", "incident_active": false } ], "total": 10 } ``` # Authentication Source: https://docs.wede.pt/authentication How to authenticate with the Wede API ## API Key Every Wede tenant has an API key. You can find yours in [Settings](https://app.wede.pt/dashboard/settings). API keys have the format: `wede_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` ## Using your API key Pass your API key in the `x-wede-api-key` header: ```bash theme={null} curl https://api.wede.pt/v1/tenant/zones \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## JWT Authentication For user-level access (dashboard, admin operations), authenticate with email and password to receive a JWT token: ```bash theme={null} curl -X POST https://api.wede.pt/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "your@email.com", "password": "your_password" }' ``` Response: ```json theme={null} { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_in": 28800, "user": { "id": "uuid", "email": "your@email.com", "name": "Your Name", "rbac_level": "company_admin" } } ``` Use the token in the `Authorization` header: ```bash theme={null} curl https://api.wede.pt/v1/tenant/zones \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` JWT tokens expire after **8 hours**. ## User Roles Wede uses role-based access control. Each user has one of the following roles: | Role | Description | | ------------------------ | -------------------------------------------- | | `company_admin` | Full access to tenant resources | | `company_tech` | Technical access - API, webhooks, zones | | `operational_supervisor` | Operational access - events, zones, dispatch | | `field_operator` | Field access - events and zone status | | `corporate_client` | Read-only access to reports | | `api_user` | API-only access, no dashboard | ## Security Never expose your API key in client-side code, public repositories, or logs. * Store API keys in environment variables * Rotate keys regularly via the [dashboard](https://app.wede.pt/dashboard/settings) * Use the minimum required permissions for each integration * All API traffic is encrypted in transit over HTTPS # Changelog Source: https://docs.wede.pt/changelog API and SDK version history ## v1.2.0 - 9 June 2026 ### New - Offline-First Device Sync (Passo 6) * `POST /v1/devices/register` — register a device for offline-first operation with permanent device ID * `POST /v1/devices/sync` — sync offline dispatch queue; idempotent at `(device_id, sequence_number)` level * `GET /v1/devices/:id/queue` — get pending (unsynced) queue for a device * Offline queue: immutable until server confirms, monotonic sequence numbers, survives app restarts ### New - Dispatch Settings * `PATCH /v1/tenant/dispatch-settings` — configure auto-dispatch, threshold, and reinforcement timeout * `dispatch_mode` — enable/disable auto-dispatch * `dispatch_threshold` — minimum score for auto-dispatch (0–1) * `reinforcement_timeout_min` — minutes before backup auto-dispatch if team doesn't ACK (0 = disabled) ### Updated - Missions * Mission status lifecycle corrected: `CREATED → SENT → ACK → ON_ROUTE → ON_SITE → COMPLETED | FAILED` * `COMPLETED` and `FAILED` now automatically close the originating event and return team to `available` * `missions:receive` permission allows field operators to update status (previously only `missions:manage`) * Backup dispatch: send a second team to an active mission using `POST /v1/teams/dispatch` with the same `event_id` ### Updated - Dispatch * `event_lat` and `event_lng` now optional (undefined when GPS not available, previously NaN) * `requires_manual: true` returned when no team meets auto-dispatch threshold * Auto-reinforcement: scheduler job checks every minute for missions without ACK beyond timeout ### SDKs - v1.2 All five SDKs updated (JS, React Native, Android/Kotlin, Swift, Python): * `requestBackup(missionId, eventId, eventLat?, eventLng?)` — request backup team for active mission * `updateDispatchSettings(dispatchMode?, dispatchThreshold?, reinforcementTimeoutMin?)` — configure dispatch settings * Offline components: `ScoreEngine`, `WedeCache`, `WedeOfflineDispatch`, `WedeDeviceId` — full offline-first capability * New SDK: `Wedeadmin/wede-sdk-android` (Kotlin) — paridade com JS/RN/Swift/Python *** ## v1.1.0 - 27 May 2026 ### New - Teams and Dispatch * `GET /v1/teams` - list teams with members and GPS coordinates * `GET /v1/teams/:id` - get team detail * `PATCH /v1/teams/:id/members/:memberId/location` - update member GPS location * `POST /v1/teams/dispatch/score` - proximity score engine - ranks teams by distance, equipment, availability and vertical capability * `POST /v1/teams/dispatch` - dispatch a team to an event - stores `event_lat`/`event_lng` for route mapping ### New - Missions * `GET /v1/missions` - list missions with filters by team, status and limit * `GET /v1/missions/:id` - get mission detail * `PATCH /v1/missions/:id/status` - update mission lifecycle status with optional feedback payload ### New - Billing * `GET /v1/tenant/billing` - current plan, annual usage counters, channel costs and available plans by country ### New - API Key Management * `GET /v1/tenant/api-keys` - list active API keys (prefix only) * `POST /v1/tenant/api-keys/rotate` - rotate API key with configurable grace period - previous key remains valid during transition ### Security * Brute force protection - account locked for 15 minutes after 5 consecutive failed login attempts - self-unlock via password reset * JWT token versioning - tokens immediately invalidated when user is suspended or reactivated * `/metrics` endpoint protected - requires `x-wede-internal` header with secret stored in GCP Secret Manager * CORS restricted to production origins only ### SDKs - v1.1 All four SDKs updated with Teams, Dispatch, Missions and Billing methods: * `@wede/sdk` (TypeScript/JavaScript) * `wede-sdk` (Python) * `@wede/react-native-sdk` (React Native) * `WedeSDK` (Swift) *** ## v1.0.0 - May 2026 ### Core Platform * `POST /v1/events` - submit events with automatic channel selection * `GET /v1/events` - list events by zone and vertical * `POST /v1/sync/batch` - sync offline event batches * `GET /v1/sync/status` - check sync batch status * `GET /v1/connectivity/status` - zone connectivity state * `POST /v1/connectivity/report` - report connectivity from field device * `GET /v1/zones` - list zones with geofence boundaries * `GET /v1/parsers` - list event parsers by vertical * `GET /v1/tenant/me` - tenant info and feature flags * `GET /v1/tenant/usage` - usage stats by period * `POST /v1/webhooks` - create webhook * `GET /v1/webhooks` - list webhooks * `DELETE /v1/webhooks/:id` - delete webhook ### Auth * `POST /v1/auth/login` - email and password login - returns JWT * `POST /v1/auth/forgot-password` - request password reset * `POST /v1/auth/reset-password` - reset password with token * `POST /v1/auth/change-password` - change password (authenticated) * `POST /v1/auth/verify` - verify account activation token ### Infrastructure * PostgreSQL 16 on GCP Cloud SQL europe-west1 * GCP Cloud Run with graceful shutdown * GitHub Actions CI/CD * Cloudflare DNS and CDN * All secrets in GCP Secret Manager * Helmet, CORS, rate limiting per tenant ### SDKs - v1.0 * `@wede/sdk` (TypeScript/JavaScript) * `wede-sdk` (Python) * `@wede/react-native-sdk` (React Native) - with offline queue via AsyncStorage * `WedeSDK` (Swift) - iOS 15+ / macOS 12+ # ISMS Source: https://docs.wede.pt/compliance/isms Information Security Management System — ISO/IEC 27001:2022 aligned policy overview Wede Technology maintains a formal Information Security Management System (ISMS) aligned with ISO/IEC 27001:2022. This page summarises the key controls and posture. The full policy document (WEDE-ISMS-001) is available to enterprise customers and auditors on request. ## Scope The ISMS covers: * Wede API platform (GCP Cloud Run, europe-west1) * Wede dashboard (Vercel, app.wede.pt) * All SDKs (JS/TS, Python, React Native, Swift, Android) * PostgreSQL 16 databases (Cloud SQL, europe-west1) * All source code repositories (GitHub, Wedeadmin organisation) * All customer (Tenant) data processed by the platform ## Security Controls Summary ### Access Control * 7-level RBAC enforced at database and middleware layers — privilege escalation is structurally impossible * JWT tokens expire after 8 hours with immediate revocation capability * API keys stored as bcrypt hashes — plaintext never retained * Brute force protection with progressive lockout ### Cryptography * TLS 1.2+ on all communications — no plaintext fallback * AES-256 encryption at rest (GCP Cloud SQL) * All secrets managed via GCP Secret Manager — never in code or environment variables * Device offline queue encrypted by operating system keychain/keystore ### Audit and Logging * Immutable audit log enforced by PostgreSQL BEFORE UPDATE/DELETE trigger * Every operation logged with user identity, action, entity, NTP timestamp, and IP * Log cannot be modified or deleted — not even by wede\_global\_admin * Minimum 5-year retention for compliance purposes * Available via API: `GET /v1/audit` and `GET /v1/compliance/report` ### Monitoring * GCP Cloud Monitoring with 4 active alerts (5xx rate, latency, instances, memory) * All alerts routed to [security@wede.pt](mailto:security@wede.pt) * GitHub Dependabot for dependency vulnerability scanning * Continuous E2E test suite (57 tests, 0 failures) running against staging on every commit ### Change Management * All changes via GitHub with mandatory TypeScript compilation check * CI/CD pipeline (GitHub Actions) with staging before production * Database migrations applied in sequence — state tracked in schema\_migrations ### Business Continuity * 99.9% monthly API availability objective * Offline-first SDK architecture — operations continue without internet * Automatic channel fallback: Internet → structured protocol → Voice * GCP Cloud Run auto-scaling and zero-downtime deployments ## Compliance Framework | Standard | Status | Notes | | ------------------- | ----------- | ----------------------------------------------------------------------------- | | ISO/IEC 27001:2022 | In progress | ISMS established. Certification audit planned. | | GDPR (EU) 2016/679 | Implemented | Data in EU, DPA with sub-processors, Privacy Policy published | | DORA (EU) 2022/2554 | Aligned | Audit trail, incident classification, operational continuity | | NIS2 Directive | Aligned | Security controls, incident reporting framework | | HIPAA | Planned | Opaque payload architecture. BAA planned before first US healthcare customer. | ## Sub-processors | Sub-processor | Service | Certifications | | ------------------------ | ----------------------------------------------- | ------------------------ | | Google Cloud Platform | Infrastructure, database, secrets | ISO 27001, SOC 2 Type II | | Resend | Transactional email | SOC 2 Type II | | Communications providers | Structured protocol and voice fallback channels | ISO 27001, SOC 2 | | Stripe | Payment processing | PCI DSS Level 1, SOC 2 | | Vercel | Dashboard hosting | SOC 2 Type II | ## Known Gaps Wede is an early-stage company. The following gaps are documented and under active remediation: * DPO not yet formally designated * External penetration test not yet completed (CREST/CHECK accredited provider planned) * ISO 27001 formal certification not yet obtained * HIPAA BAA not yet established ## Contact For security enquiries, responsible disclosure, or audit documentation requests: * Security: [security@wede.pt](mailto:security@wede.pt) * Privacy: [privacy@wede.pt](mailto:privacy@wede.pt) * General: [geral@wede.pt](mailto:geral@wede.pt) The full ISMS Policy document (WEDE-ISMS-001, 16 sections, ISO/IEC 27001:2022 Annex A mapped) is available to enterprise customers and auditors on request at [security@wede.pt](mailto:security@wede.pt). # Compliance Report Source: https://docs.wede.pt/compliance/report Operational and security compliance reporting for ISO 27001, DORA, GDPR and NIS2 The Wede compliance report provides a daily breakdown of operational, security, and continuity data for audit and regulatory purposes. It is aligned with ISO 27001:2022, DORA, GDPR, and NIS2. ## Endpoint ```text theme={null} GET /v1/compliance/report ``` Requires authentication. Accessible to `company_admin`, `company_tech`, `country_admin`, `wede_tech_ops`, and `wede_global_admin`. ## Parameters | Parameter | Type | Default | Description | | ------------- | ------------------- | ----------- | ------------------------------- | | `from` | string (YYYY-MM-DD) | 30 days ago | Start of reporting period | | `to` | string (YYYY-MM-DD) | Today | End of reporting period | | `granularity` | string | `day` | Always `day` in current version | ## Example ```bash theme={null} curl https://api.wede.pt/v1/compliance/report?from=2026-06-01&to=2026-06-30 \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Response Structure ```json theme={null} { "meta": { "from": "2026-06-01", "to": "2026-06-30", "granularity": "day", "tenant_id": "9c145f7e-...", "generated_at": "2026-06-12T08:30:37Z", "standards": ["ISO 27001:2022", "DORA", "GDPR", "NIS2"] }, "data": { "events": [...], "missions": [...], "dispatch": [...], "security": [...], "offline_sync": [...], "webhooks": [...], "active_users": [...], "audit_volume": [...] } } ``` ## Data Sections ### events Operational events per day, grouped by vertical. | Field | Description | | ----------- | ----------------------------------------- | | `day` | Date (YYYY-MM-DD) | | `vertical` | Operational vertical (e.g. healthcare) | | `total` | Total events created | | `completed` | Events with missions closed as COMPLETED | | `failed` | Events with missions closed as FAILED | | `pending` | Events awaiting dispatch or mission close | ### missions Mission lifecycle per day. | Field | Description | | -------------------- | --------------------------------------------- | | `day` | Date | | `total` | Total missions created | | `completed` | Missions completed successfully | | `failed` | Missions closed as failed | | `avg_resolution_min` | Average time from creation to close (minutes) | ### dispatch Dispatch operations per day. | Field | Description | | ------------------- | -------------------------------------------------------------- | | `day` | Date | | `total_dispatches` | Total team dispatches | | `auto_dispatches` | Auto-dispatched by score engine | | `manual_dispatches` | Manually dispatched by operator | | `tier1` | Dispatches to Tier 1 teams (action-allocated, full capability) | | `tier2` | Dispatches to Tier 2 teams (action-allocated, partial) | | `tier3` | Dispatches to Tier 3 teams (vertical fallback) | ### security Security events per day. Required for ISO 27001 and DORA audit trails. | Field | Description | | --------------------- | ----------------------------------------------------- | | `day` | Date | | `auth_failures` | Failed authentication attempts | | `successful_logins` | Successful logins | | `parser_violations` | Attempts to modify protected parser fields (rejected) | | `api_key_revocations` | API keys revoked | | `user_suspensions` | Users suspended | ### offline\_sync Offline device sync activity per day. Required for DORA operational continuity evidence. | Field | Description | | ----------------- | ------------------------------------------- | | `day` | Date | | `devices_synced` | Distinct devices that synced | | `sync_operations` | Total sync operations received | | `processed` | Successfully processed offline dispatches | | `duplicates` | Duplicate operations rejected (idempotency) | ### webhooks Webhook delivery per day. | Field | Description | | ----------- | ------------------------------- | | `day` | Date | | `delivered` | Successfully delivered webhooks | | `failed` | Failed webhook deliveries | ### active\_users User activity per day. | Field | Description | | --------------- | ------------------------------------------------ | | `day` | Date | | `active_users` | Distinct users who performed at least one action | | `total_actions` | Total actions performed by users | ### audit\_volume Audit log statistics per day. The audit log is immutable — enforced by database trigger. | Field | Description | | ------------------ | --------------------------------- | | `day` | Date | | `total_entries` | Total immutable audit log entries | | `distinct_users` | Users who generated audit events | | `distinct_actions` | Distinct action types recorded | *** ## Export To download the report as a JSON file: ```bash theme={null} curl "https://api.wede.pt/v1/compliance/report/export?from=2026-06-01&to=2026-06-30" \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -o wede-compliance-report.json ``` *** ## Dashboard The compliance report is also available in the Wede dashboard at **app.wede.pt/dashboard/compliance**, with four tabs: * **Operations** — events, missions, dispatch by day * **Security** — auth failures, parser violations, webhook delivery * **Continuity** — offline sync activity (DORA evidence) * **Audit Volume** — immutable audit log statistics The dashboard supports date range selection and JSON export. *** ## Standards Alignment | Standard | Relevant sections | | ------------------ | ---------------------------------------------------------------------- | | **ISO 27001:2022** | security (auth failures, violations), audit\_volume, active\_users | | **DORA** | offline\_sync (continuity evidence), dispatch (operational resilience) | | **GDPR** | audit\_volume (access log), active\_users (data subject activity) | | **NIS2** | security, missions (incident response time), offline\_sync | The audit log underlying this report is immutable by construction. Entries are written by a PostgreSQL BEFORE UPDATE/DELETE trigger that cannot be bypassed by application code, not even by wede\_global\_admin. This provides tamper-evident evidence for regulatory audits. # Connectivity Source: https://docs.wede.pt/concepts/connectivity How Wede monitors and manages connectivity across operational zones ## Real-Time Monitoring Wede continuously monitors connectivity across all operational zones. Each zone has an independent connectivity state that reflects current network conditions in that geographic area. State changes are detected automatically and trigger channel switching without any action required from your integration. ## Connectivity States | State | Description | Action | | ------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------ | | **online** | Full internet connectivity | Primary REST channel active | | **degraded** | Reduced bandwidth or reliability | Compressed REST, optimised routing | | **sms\_only** | Internet unavailable | Structured protocols active; additional fallback protocols engage automatically per plan configuration | | **offline** | All external channels down | Events queue locally with guaranteed sync on reconnection | ## Continuity Modes Every Wede plan operates in one of two continuity modes, configured per tenant: **Automatic cascade.** When a zone's connectivity degrades, Wede transitions across channels automatically, in the priority order you define. There is no single hierarchy imposed by Wede: you choose which channels are eligible for your traffic and in what order they are tried. **Store-and-forward.** For tenants who do not need active channel switching, events queue locally and deliver once connectivity returns, without attempting intermediate fallback channels. Both modes share the same guarantee: every queued event synchronises automatically and exactly once, the moment connectivity is restored - but the two modes identify "the same operation twice" differently. Automatic cascade identifies each queued item by its device and sequence number. Store-and-forward identifies each event by a single-use, cryptographically signed reconciliation token, bound to a hash of the event's payload at issue time: redeeming the same token twice is rejected, and a payload that no longer matches its original hash is rejected and flagged for review. The channel used for each event delivery is included in the API response and webhook payload, giving you full visibility of how each event was delivered. ## Reporting Connectivity Your field devices and systems can report connectivity state to Wede: ```bash theme={null} curl -X POST https://api.wede.pt/v1/connectivity/report \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "zone_code": "zone_hospital_evora", "state": "degraded", "signal_strength": -85, "channel": "sms" }' ``` ## Checking Connectivity Status ```bash theme={null} curl https://api.wede.pt/v1/connectivity/status \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` Response: ```json theme={null} { "zones": [ { "zone_code": "zone_hospital_evora", "connectivity_state": "online", "last_updated": "2026-05-19T10:00:00Z", "channels_available": ["rest_full", "rest_compressed", "sms"] } ] } ``` ## Webhook Notifications When a zone changes connectivity state, Wede notifies your configured webhooks immediately: ```json theme={null} { "event": "zone.state_changed", "zone_code": "zone_hospital_evora", "previous_state": "online", "current_state": "sms_only", "timestamp": "2026-05-19T10:15:00Z" } ``` Configure webhooks in the [dashboard](https://app.wede.pt/dashboard/webhooks) or via the API. ## Dashboard Visibility All zone connectivity states are visible in real-time on the [dashboard map](https://app.wede.pt/dashboard). Each zone is represented by a colour-coded marker: * 🟢 **Green** - online * 🟡 **Amber** - degraded or structured-protocol-only * 🔴 **Red** - offline * ⚪ **Pulsing** - incident active # Events Source: https://docs.wede.pt/concepts/events How events work in Wede ## What is an Event An event is any operation, alert, or notification that your system needs to deliver reliably — regardless of connectivity conditions. Events are the core primitive of the Wede platform. You send an event, Wede guarantees delivery through the best available channel. An event can originate anywhere in your system, a dispatcher, a field team member, or a request from your own end customer. Wede does not care who or what creates it. ## Event Structure ```json theme={null} { "type": "EMERGENCY_DISPATCH", "priority": "critical", "vertical": "healthcare", "idempotency_key": "dispatch-2026-05-19-amb07-001", "payload": { "unit": "AMB-PT-07", "location": "Hospital Santa Maria, Lisboa" } } ``` | Field | Required | Description | | ----------------- | -------- | -------------------------------------------------------- | | `type` | Yes | Event type — freeform string, uppercase recommended | | `priority` | Yes | `critical`, `high`, `normal`, or `low` | | `vertical` | Yes | Industry vertical — see [Verticals](/concepts/verticals) | | `idempotency_key` | Yes | Unique key to prevent duplicate processing | | `payload` | No | Arbitrary JSON payload — your data, opaque to Wede | | `zone_code` | No | Target zone — routes to specific operational area | ## Priority Levels | Priority | Description | Channel Behaviour | | ---------- | ------------------------------------- | ---------------------------------- | | `critical` | Immediate delivery required | All channels attempted in parallel | | `high` | Fast delivery, minor delay acceptable | Primary + fallback channels | | `normal` | Standard delivery | Primary channel with fallback | | `low` | Best-effort delivery | Primary channel only | ## Event Response ```json theme={null} { "event_id": "0ee3dfbe-1234-abcd-5678-ef90ab12cd34", "status": "pending", "channel_selected": "rest_full", "created_at": "2026-05-19T10:00:00Z" } ``` ## Event Status | Status | Meaning | | ---------------- | ---------------------------------------------- | | `pending` | Accepted, awaiting delivery | | `delivered` | Successfully delivered | | `failed` | Delivery failed after all retries | | `queued_offline` | Queued for delivery when connectivity restores | ## Event Examples by Vertical **Healthcare:** ```json theme={null} { "type": "ICU_ALERT", "priority": "critical", "vertical": "healthcare", "idempotency_key": "icu-alert-2026-05-19-ward3b-001", "payload": { "patient_id": "PT-9821", "ward": "3B", "alert": "cardiac_arrhythmia", "nurse_call": true } } ``` **Banking:** ```json theme={null} { "type": "PAYMENT_DECLINED", "priority": "high", "vertical": "banking", "idempotency_key": "payment-decline-term042-20260519-001", "payload": { "terminal_id": "POS-NG-042", "reason": "connectivity_timeout", "amount": 45000, "currency": "NGN" } } ``` **Logistics:** ```json theme={null} { "type": "SHIPMENT_DELAYED", "priority": "normal", "vertical": "delivery", "idempotency_key": "shipment-delay-ord29841-20260519", "payload": { "order_id": "ORD-29841", "driver_id": "DRV-KE-019", "reason": "road_closure", "new_eta": "2026-05-19T16:30:00Z" } } ``` **Telecom:** ```json theme={null} { "type": "TOWER_DOWN", "priority": "critical", "vertical": "telecom", "idempotency_key": "tower-down-bts112-20260519-001", "payload": { "site_id": "BTS-AE-112", "location": "Dubai — Al Barsha", "cause": "power_failure", "affected_subscribers": 8400 } } ``` **Government:** ```json theme={null} { "type": "CIVIL_PROTECTION_ALERT", "priority": "critical", "vertical": "gov", "idempotency_key": "civil-alert-maputo-norte-20260519", "payload": { "zone": "zona_norte_maputo", "alert_type": "flood_warning", "severity": "red", "population_affected": 34000 } } ``` ## Listing Events ```bash theme={null} curl https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` ## Idempotency Always provide a unique `idempotency_key` per logical event. If the same key is submitted twice, Wede processes it once and returns the original response. Good idempotency keys include: * Timestamp + entity + sequence: `dispatch-2026-05-19-amb07-001` * Your internal event ID: `internal-evt-id-84729` * UUID: `550e8400-e29b-41d4-a716-446655440000` # Geofencing Source: https://docs.wede.pt/concepts/geofencing How zone boundaries control team eligibility for dispatch ## Overview Each zone can have a polygon boundary defined — a set of GPS coordinates that form a closed shape on the map. The score engine uses this boundary to determine whether a team is the right match for an event. ## How it works When an event occurs at a given GPS location, the score engine checks whether that location falls inside each team's zone boundary using a **point-in-polygon ray casting algorithm**. This runs identically on the API (online) and on the SDK (offline) — the same result, no server required. Teams outside the event zone are ranked lower by the score engine, but not excluded — cross-zone escalation is always possible. ## Defining a boundary Zone boundaries are defined in the dashboard under **Zones → Edit Zone**. Click on the map to place polygon points. The boundary is saved as a JSONB array of `{ lat, lng }` coordinates. ```json theme={null} { "boundary": [ { "lat": 38.72, "lng": -9.14 }, { "lat": 38.71, "lng": -9.13 }, { "lat": 38.70, "lng": -9.15 }, { "lat": 38.72, "lng": -9.14 } ] } ``` A valid polygon requires at least 3 points. ## Offline compatibility Zone boundaries are stored locally on the SDK. The point-in-polygon check runs without any network connection — the same algorithm, the same result as the API. ## Teams without a boundary If a zone has no boundary defined, the geofence check is skipped and no penalty is applied. All teams remain fully eligible. # Metering & Usage Source: https://docs.wede.pt/concepts/metering How wede tracks and bills operational usage ## Overview Every operation on the wede platform is metered and debited from the tenant's annual plan. Usage is tracked in real time in the `tenant_annual_usage` table and visible in the billing dashboard. ## Billable operations | Operation | Trigger | Channel cost | | ----------------------------- | ------------------------------------------------------------------------ | ---------------------- | | Event via internet | `POST /v1/events` with internet channel | No extra cost | | Event via structured protocol | `POST /v1/events` with structured channel | Yes - per unit | | Event via voice | `POST /v1/events` with voice channel | Yes - per voice minute | | Event via LoRa | `POST /v1/events` with LoRa channel | Yes - per transmission | | Event via satellite | `POST /v1/events` with satellite channel | Yes - per packet | | Dispatch | `POST /v1/teams/dispatch` | No extra cost | | Mission created | `POST /v1/missions` | No extra cost | | Location update offline | `PATCH /v1/teams/:id/members/:memberId/location` with structured channel | Yes - per unit | Internet-based operations (events, dispatch, missions, location updates via IP) count against the plan's `max_events_per_year` limit. Off-channel operations (structured protocols, voice, LoRa, satellite) also incur the per-unit channel cost defined in `country_channel_costs`. ## Annual plans All wede plans are annual. There are no monthly plans. * Plan limits reset on the plan anniversary date * Overage is billed at the per-unit channel rate * Tenants can pre-load credit or be invoiced at period end ## Usage tracking Usage is accumulated in `tenant_annual_usage`: ```json theme={null} { "events_total": 12400, "events_internet": 12100, "events_sms": 280, "events_voice": 20, "location_updates_offline": 840, "dispatches_total": 156, "dispatches_offline": 12, "missions_total": 156, "overage_events": 0, "overage_amount_eur": 0 } ``` ## Overage When `events_total` exceeds `max_events_per_year`: * Operations continue without interruption * `overage_events` counter increments * `overage_amount_eur` accumulates at the overage rate * Tenant is notified at 70%, 80% and 90% consumption thresholds ## Channel costs Channel costs are defined per country, per channel in `country_channel_costs`. Each country has independent pricing reflecting local telco rates. ```json theme={null} [ { "channel": "sms", "cost_per_unit": 0.04, "currency": "EUR" }, { "channel": "voice", "cost_per_unit": 0.08, "currency": "EUR" }, { "channel": "lora", "cost_per_unit": 0.01, "currency": "EUR" } ] ``` # Offline-First Architecture Source: https://docs.wede.pt/concepts/offline-first How Wede ensures operational continuity without internet ## What Offline-First Means Most platforms assume internet connectivity. They are built for the best case. When connectivity fails, they fail too. Wede is built for the worst case. Every feature, every integration, every delivery guarantee is designed to work without internet — and to work better when internet is available. This is what offline-first means: not a fallback mode, but the default architecture. *** ## Delivery Channels Wede maintains multiple delivery channels for every operational zone. When the primary channel degrades, the next channel activates automatically — transparently, without any changes to your integration. | Channel | Description | Best For | | ------------------------ | ----------------------------------------------------- | ------------------------------------------------- | | **REST Full** | Standard HTTPS, primary channel | Normal operations | | **REST Compressed** | Optimised low-bandwidth HTTPS | Degraded internet | | **Structured Protocols** | Compact structured transmission | When internet is unavailable | | **Voice** | Voice call delivery | Critical alerts, no data | | **LoRa** | Long-range IoT radio, up to 15 km range | Remote areas, rural infrastructure | | **Satellite** | Global satellite coverage via third-party integration | Extreme environments, conflict zones, no cellular | | **Edge** | Local edge processing, zero external dependency | Air-gapped environments, ultra-low latency | Wede's fallback architecture is proprietary, patent-pending technology. Every channel above is part of the same provider-agnostic integration layer, extended channel by channel; reach out for the current rollout status in your target markets. Channel selection is automatic and transparent. Your API call stays the same regardless of which channel delivers the event. *** ## Connectivity States Each zone has an independent connectivity state, monitored in real-time: | State | Meaning | Channels Active | | ------------- | --------------------------------- | -------------------------------------------------------------------------------------- | | **online** | Full connectivity | REST Full, REST Compressed | | **degraded** | Reduced connectivity | REST Compressed, Structured Protocols | | **sms\_only** | Internet unavailable | Structured Protocols active, extended fallback protocols engage per plan configuration | | **offline** | All internet channels unavailable | Queue mode, guaranteed sync on reconnect | Zone states are visible in real-time in your [dashboard](https://app.wede.pt/dashboard/zones) and via the API. *** ## Device Registration and Offline Queue Wede provides a device-level offline guarantee through the Device Sync API. When a device registers, it receives a permanent `device_id` that survives app reinstalls and cache clears. ### Register a Device `POST /v1/devices/register` ```json theme={null} { "device_id": "generated-on-install-uuid", "platform": "android", "app_version": "2.1.0" } ``` ### Offline Dispatch Queue When a device is offline, dispatches are queued locally with monotonic sequence numbers. Each entry is immutable — it is never deleted until the server confirms receipt. ```typescript theme={null} // SDK — offline dispatch (works without internet) const result = await offline.dispatch('cardiac_arrest', { lat: 38.7169, lng: -9.1395, vertical: 'healthcare', priority: 'high' }) // result.queued === true — stored locally, will sync automatically ``` ### Sync on Reconnection `POST /v1/devices/sync` When connectivity is restored, the SDK automatically syncs the queue: ```json theme={null} { "device_id": "uuid", "last_received_seq": 42, "dispatches": [ { "sequence_number": 43, "action_id": "uuid", "event_lat": 38.7169, "event_lng": -9.1395, "vertical": "healthcare", "priority": "high", "created_offline_at": "2026-06-09T17:00:00Z" } ] } ``` The server responds with: ```json theme={null} { "accepted": [43], "duplicates": [], "failed": [], "server_seq": 43, "device_last_received_seq": 42, "synced_at": "2026-06-09T18:00:00Z" } ``` **Idempotency** is enforced at the `(device_id, sequence_number)` level — retransmitting the same entry is safe and will be returned in `duplicates`, not processed twice. ### Get Pending Queue `GET /v1/devices/:id/queue` Returns all unsynced entries for a device — useful for monitoring offline operations from the server side. *** ## SDK Offline Architecture All Wede SDKs include three offline components: | Component | Purpose | | ----------------------- | --------------------------------------------------------------------- | | **ScoreEngine** | Ranks teams locally using cached data — no server call needed | | **WedeCache** | Local cache of teams and catalog (TTL 5 min) — feeds the score engine | | **WedeOfflineDispatch** | Queues dispatches offline with immutable sequence numbers | ```typescript theme={null} // JS/TS — full offline flow import { WedeClient, WedeCache, WedeOfflineDispatch } from '@wede/sdk' const cache = new WedeCache(storage) const offline = new WedeOfflineDispatch(storage, cache) // When offline: score locally, queue dispatch const result = await offline.dispatch('cardiac_arrest', { lat: 38.7169, lng: -9.1395, vertical: 'healthcare' }) // When online: sync queue await client.syncDeviceQueue(deviceId) ``` The same architecture is available in all SDKs: | SDK | Offline Module | | ----------------------- | --------------------- | | JavaScript / TypeScript | `WedeOfflineDispatch` | | React Native | `WedeOfflineDispatch` | | Android (Kotlin) | `WedeOfflineDispatch` | | iOS (Swift) | `WedeOfflineDispatch` | | Python | `WedeOfflineDispatch` | *** ## Idempotency Every event sent to Wede requires an `idempotency_key`. This guarantees that even if the same event is sent multiple times — due to network retries or reconnection — it is processed exactly once. ```json theme={null} { "type": "EMERGENCY", "priority": "critical", "vertical": "healthcare", "idempotency_key": "dispatch-2026-06-09-amb07-001" } ``` Choose idempotency keys that are unique per logical event — not per API call. *** ## Security All communication is encrypted in transit over HTTPS. Events are authenticated using your API key or JWT token. All operations are logged in an immutable audit trail. Offline queues are stored locally on the device. They do not contain sensitive payload data — only operational metadata (action type, coordinates, vertical, priority). *** ## Compliance Wede's architecture is designed from the ground up around the requirements that matter to regulated industries and the communications protocols used globally: * **GDPR** — data residency and processing within EU infrastructure (GCP europe-west1), data minimisation by design * **DORA** — ICT risk management, operational resilience and incident reporting for financial entities operating in the EU * **ISO 27001-aligned controls** — access management, audit trail and information security practices * **CBUAE** — resilience and reporting expectations for financial institutions in the UAE * **Audit trail** — every operation logged with user, timestamp and IP, immutable and cryptographically traceable * **Role-based access** — granular permissions per user role * **Confidentiality** — Wede does not access or define your operational content; data and configuration are isolated per tenant # Parsers Source: https://docs.wede.pt/concepts/parsers Configure how event data is structured, encoded and transmitted across channels - including offline via structured protocols ## What is a Parser? A parser defines the data structure for events in a specific vertical. It controls which fields are collected, how they are encoded for transmission, and whether they can be sent offline via structured protocols when internet connectivity is unavailable. Each parser belongs to a tenant and is scoped to a vertical - `healthcare`, `banking`, `emergency`, `logistics`, `telecom`, or `gov`. A tenant can have multiple parser versions per vertical, but only one is active at a time. ## Why Parsers Matter In environments where connectivity is unreliable, every byte counts. When an event cannot be sent via REST, Wede falls back to structured protocols. A parser ensures that the most critical fields are encoded efficiently - fitting into as few protocol units as possible - while preserving data integrity and legal compliance. A well-configured parser means your operations continue without interruption, regardless of network conditions. ## Field Sections Each parser is composed of fields organised into sections: | Section | Purpose | | ---------- | --------------------------------------------------------- | | `core` | Mandatory identifiers and timestamps - always transmitted | | `location` | GPS coordinates and addresses | | `human` | Person data - subject to legal and GDPR requirements | | `hardware` | Equipment, vehicle and device identifiers | | `team` | Responder team, dispatch and capacity data | | `custom` | Tenant-defined free fields | ## Field Types | Type | Description | Max Bytes | | ------------- | ------------------------------ | --------- | | `string` | Short text | 20 | | `number` | Numeric value | 8 | | `boolean` | Yes/No flag | 1 | | `gps` | Latitude/longitude coordinates | 18 | | `text` | Free text (longer) | 80 | | `timestamp` | ISO date/time | 14 | | `enum` | Fixed set of values | 6 | | `phone` | Phone number | 15 | | `email` | Email address | 30 | | `address` | Free text address | 60 | | `hardware_id` | Device or equipment ID | 16 | ## Structured Encoding Wede calculates the estimated byte size of each enabled field and the total payload size. If the payload exceeds 140 bytes, it is automatically fragmented and reassembled at the destination - transparently, without changes to your integration. Each field is encoded as compact key-value pairs. The field code is a short identifier (up to 8 characters) that minimises transmission size. Fields marked `offline_capable: false` are excluded when transmitting via structured protocols. ## Legal Fields Fields marked `legal: true` contain personally identifiable information (PII). These fields are subject to GDPR and local data protection regulations. Wede logs access to legal fields in the audit trail automatically. ## Versioning When you update a parser schema, Wede creates a new version. The previous version is deactivated but retained for audit purposes. All events are tagged with the parser version active at the time of creation. ## Parser Protection — Three Layers Parsers are protected at three levels to prevent accidental or malicious modification of critical fields: | Protection | Flag | Description | | ------------- | ----------------- | ------------------------------------------------------------------------------------------------------ | | **Integrity** | `integrity: true` | Fields required for event identity (event\_id, timestamp, tenant\_id). Cannot be disabled or modified. | | **Legal** | `legal: true` | Fields containing PII subject to GDPR. Modification is logged as a compliance event. | | **Locked** | `locked: true` | Operationally critical fields (dispatch triggers, channel selectors). Require admin override. | Attempts to modify protected fields are rejected and recorded in the Audit Log as `parser.update.rejected`. ## Action Catalog Integration The `event_type` field in a parser points to the **action catalog** — not a hardcoded list. This means: * The tenant defines which event types exist (via the catalog) * The parser `event_type` field references catalog action codes * Teams are linked to catalog actions to determine dispatch eligibility To configure event types for a parser, go to **Parsers → Actions tab** in the dashboard and link catalog actions. ## Automatic Seed on Vertical Assignment When a vertical is assigned to a tenant, Wede automatically seeds a default parser for that vertical. The seed parser includes: * Core integrity fields (locked) * Standard legal fields (locked) * Vertical-specific operational fields (configurable) The tenant can extend the seeded parser with custom fields but cannot remove core or legal fields. ## Roles & Access | Role | Access | | ------------------------------------ | ----------------------------------------- | | `wede_global_admin`, `wede_tech_ops` | All parsers across all tenants | | `country_admin` | Parsers for tenants in assigned countries | | `company_admin`, `company_tech` | Own tenant parsers, own verticals only | | `operational_supervisor` | Read-only view | | `field_operator` | No parser access | ## Example - Healthcare Parser A minimal healthcare parser for offline-capable emergency events: ```json theme={null} { "vertical": "healthcare", "name": "Healthcare v1", "schema": [ { "id": "hc_eid", "name": "event_id", "sms_code": "eid", "type": "string", "required": true, "enabled": true, "offline_capable": true, "section": "core", "max_bytes": 12 }, { "id": "hc_ts", "name": "timestamp", "sms_code": "ts", "type": "timestamp", "required": true, "enabled": true, "offline_capable": true, "section": "core", "max_bytes": 14 }, { "id": "hc_typ", "name": "event_type", "sms_code": "typ", "type": "enum", "required": true, "enabled": true, "offline_capable": true, "section": "core", "max_bytes": 6, "enum_values": ["CARDIAC", "TRAUMA", "STROKE", "RESPIRATORY", "OTHER"] }, { "id": "hc_pid", "name": "patient_id", "sms_code": "pid", "type": "string", "required": true, "enabled": true, "offline_capable": true, "section": "human", "max_bytes": 16, "legal": true }, { "id": "hc_gps", "name": "requester_gps", "sms_code": "rgps", "type": "gps", "required": true, "enabled": true, "offline_capable": true, "section": "location", "max_bytes": 18 } ] } ``` This parser fits in a single protocol unit (approximately 90 bytes), ensuring delivery even on the most degraded networks. # Plans Source: https://docs.wede.pt/concepts/plans How Wede plans and the communications model work ## Plans Wede plans start with a Pilot or Store & Forward foundation, then scale through Starter, Growth, and Mission-Critical tiers, each with progressively more customisable integrations, channel priority control, and zone capacity. The plan a tenant is on determines its continuity mode, the number of zones it can operate, and how many channel integrations it can configure. See [Continuity Modes](/concepts/connectivity) for the difference between store-and-forward and automatic cascade. ## Communications model Wede supports two ways to access communications channels: * **Bulk access.** Wede provides bulk access to its communications network across channels, so you never have to negotiate with individual providers yourself. * **Direct negotiation.** Your organisation can negotiate directly with your own communications providers, telecom operators, satellite carriers, or LoRa network operators, and connect them through Wede. In this model, a valid Wede licence is all that's required, with no communication cost passed through Wede. Both models run through the same integration layer and the same fallback architecture, your integration code does not change based on which model you choose. # Score Engine Source: https://docs.wede.pt/concepts/score-engine How wede ranks teams for dispatch using proximity, equipment and capability ## Overview The wede score engine ranks available teams for a given event, combining proximity, equipment match, member availability, current load, and zone geofence into a single ranking. It runs identically on the API (online) and on the SDK (offline) - no server required, no external dependencies. Teams are ranked from best match to worst. The top-ranked team is marked as `recommended`. ## Tier System Teams are ranked within three dispatch tiers before scoring: | Tier | Eligibility | Description | | ---------- | ----------------------------------------------- | ----------------------------------- | | **Tier 1** | Allocated to action + has required capabilities | Best match — preferred for dispatch | | **Tier 2** | Allocated to action, missing some capabilities | Acceptable fallback | | **Tier 3** | Same vertical, not allocated to action | Last resort — cross-capability | Tier 1 teams are always preferred over Tier 2, regardless of ranking within tier. ## What the ranking considers * **Proximity** - great-circle distance between the team's current position and the event, weighted toward estimated arrival time * **Capability match** - how closely the team's equipment matches what the event requires * **Member availability** - how many of the team's members are currently available * **Current load** - teams already on a mission are ranked lower * **Zone geofence** - teams outside the event's zone boundary are ranked lower, but not excluded; cross-zone escalation is always possible The exact ranking algorithm, including its weighting, is proprietary, patent-pending technology. ## Position resolution The engine resolves each team's position from the freshest source available - recent member GPS, any known member GPS, or the team's zone center, in that order. A team without any position data can still be scored and dispatched. ## Fallback channel Based on estimated time to arrival and event priority, the engine recommends the appropriate delivery channel for the dispatch notification, favouring a structured fallback protocol for time-critical or long-ETA events, and the primary channel otherwise. ## Offline operation The score engine is designed to run without connectivity. The SDK stores team positions, zone boundaries, equipment lists, and catalog actions locally. On offline dispatch, the SDK scores locally and queues the dispatch for sync when connectivity returns. The result is always consistent with what the API would produce. All five SDKs (JS, React Native, Android, Swift, Python) include the identical score engine implementation - zero dependencies, no server call required. # Security Source: https://docs.wede.pt/concepts/security Technical security architecture, compliance alignment, and what Wede guarantees per vertical ## Architecture Overview Wede is designed for regulated industries where security is not a feature - it is a precondition. Every architectural decision is made with the assumption that the data being transported is sensitive, the operations are critical, and the audit trail is legally required. Wede transports payloads but never inspects them. Your data is encrypted by you before it reaches Wede. We handle delivery, integrity, and reconciliation - not content. *** ## Authentication and Access ### API Keys Every tenant receives two API keys at onboarding - one for production (`wede_live_`), one for sandbox (`wede_test_`). Keys are: * Stored as **bcrypt hashes** - never in plain text, not even internally * Validated on every request with constant-time comparison * Scopeable per integration or environment * Rotatable at any time via `POST /v1/tenant/api-keys/rotate` with a configurable grace period ```bash theme={null} POST /v1/tenant/api-keys/rotate { "environment": "production", "grace_hours": 24 } ``` The previous key remains valid for the configured grace period, allowing zero-downtime rotation. ### JWT Sessions User sessions are issued as signed JWT tokens: * Signed with a secret stored in **GCP Secret Manager** - never in environment variables * Expire after **8 hours** * Include a `token_version` claim tied to the user record * Immediately invalidated when a user is suspended or their session is revoked - no waiting for expiry ### Brute Force Protection Login attempts are rate-limited at two levels: * **Global rate limit** - per tenant, configurable per plan * **Per-account lockout** - after 5 consecutive failed attempts, the account is locked for 15 minutes. The user can unlock immediately via password reset without admin intervention. *** ## Transport Security All communication with the Wede API is encrypted over **TLS 1.2+**. Unencrypted HTTP is rejected at the infrastructure level - not redirected. This applies to all delivery channels: REST, structured protocols, voice, LoRa, and satellite. Each channel has independent transport-level security appropriate to its protocol. *** ## Role-Based Access Control Wede implements a **7-level cascading RBAC** model. No level can grant permissions it does not itself hold. Privilege escalation is mathematically impossible. | Level | Role | Scope | Can configure? | | ----- | ------------------------ | --------------------------------------------------------------------- | --------------- | | 1 | `wede_global_admin` | Full platform — infrastructure, billing, all tenants | Yes | | 2 | `wede_tech_ops` | Technical operations — no billing, no tenant config | Yes (technical) | | 3 | `country_admin` | Regional management — assigned countries only | Yes (regional) | | 4 | `company_admin` | Full tenant — teams, users, billing view, dispatch | Yes | | 5 | `company_tech` | Technical — SDK, API keys, integrations, teams, dispatch | Yes | | 6 | `operational_supervisor` | Dispatch console, missions, backup — **executes, does not configure** | No | | 7 | `field_operator` | Mission receipt, status updates, backup requests — **executes only** | No | `operational_supervisor` and `field_operator` are execution roles — they dispatch teams, update mission status, and request backup. They cannot create or modify parsers, catalogs, teams, or tenant settings. Assign `company_tech` or `company_admin` for configuration access. `wede_global_admin`, `wede_tech_ops`, and `country_admin` are above-tenant roles — they do not belong to any specific organisation and **cannot dispatch teams**. Dispatch is always a tenant-level operation. Every API route enforces the minimum required permission. Attempting to access a route without the required permission returns `403 Forbidden` — the route does not exist from the caller's perspective. ### Cascade Principle * Wede Global Admin defines the full universe of available features * Each level receives a subset of the level above * Delegation is explicit — not included by default * Privilege escalation is structurally impossible — no level can grant what it does not hold *** ## Audit Trail Every mutating operation in Wede is written to an **immutable audit log**: * User identity and role * Action performed (create, update, delete, dispatch, suspend) * Resource type and ID * Timestamp (UTC) * IP address * User agent * Request ID for end-to-end traceability Covered operations include: authentication, events, sync, webhooks, teams, dispatch, missions, parsers, users, zones, and tenant configuration changes. Audit logs are available via the API (`GET /v1/audit`) and the dashboard. They cannot be modified or deleted - not even by Wede Global Admin. *** ## Data Isolation Each tenant's data is logically isolated at the database level. Every query is scoped to `tenant_id`. Cross-tenant data access is structurally impossible via the API - not just access-controlled. `country_admin` roles operate across tenants within their assigned countries via explicit `country_admin_assignments` - there is no implicit access. *** ## Payload Opacity Wede never reads, stores, or inspects the content of your event payloads. Encrypt before sending. The `payload` field in every event is treated as an opaque binary blob. Wede transports it, preserves its integrity via SHA-256 hash, and delivers it - without ever accessing its content. This is by design and enforced at the architectural level. This means Wede is compatible with end-to-end encrypted workflows in healthcare, banking, and government without any changes. *** ## Infrastructure * **Cloud provider**: GCP europe-west1 (Belgium) * **Database**: PostgreSQL 16 - Cloud SQL with automated backups * **Secrets**: GCP Secret Manager - all credentials, keys, and tokens * **Container runtime**: Cloud Run - auto-scaling, no persistent state * **CDN and DNS**: Cloudflare - DDoS protection, global PoPs All infrastructure is within the EU. Data does not leave the EU unless explicitly configured for a multi-region deployment. *** ## Compliance Alignment by Vertical ### Banking and Fintech - DORA The EU Digital Operational Resilience Act (DORA) applies to financial entities and their ICT providers. Wede is designed as a DORA-aligned ICT layer: | DORA Requirement | Wede Implementation | | ------------------------- | --------------------------------------------------------------------------- | | ICT risk management | Multi-channel fallback, zone connectivity monitoring, real-time alerts | | Incident reporting | Immutable audit log, webhook notifications, structured incident lifecycle | | Operational continuity | Offline-first SDK - operations continue without internet | | Third-party ICT oversight | Full API documentation, contractual SLAs, audit trail exportable to PDF/CSV | | Resilience testing | Sandbox environment per tenant, connectivity simulation endpoints | | Data integrity | SHA-256 hash per event, idempotency enforcement, reconciliation engine | | Access controls | 7-level RBAC, API key rotation, JWT revocation, brute force protection | | Audit trail | Immutable logs with user, action, timestamp, IP, request ID | Wede operates as an ICT third-party provider under DORA Article 28. Full contractual documentation is available on request. ### Healthcare - HIPAA and MDR For healthcare deployments, Wede aligns with HIPAA Technical Safeguards (45 CFR § 164.312): | HIPAA Safeguard | Wede Implementation | | ------------------------------------ | ------------------------------------------------------------------------- | | Access Controls (§ 164.312(a)) | RBAC with unique user IDs, automatic session expiry, role-scoped API keys | | Audit Controls (§ 164.312(b)) | Session-level and operation-level audit logs, tamper-evident, exportable | | Integrity Controls (§ 164.312(c)) | SHA-256 per event, idempotency key, reconciliation without data loss | | Transmission Security (§ 164.312(e)) | TLS 1.2+ enforced, no unencrypted fallback paths | | Authentication | JWT with token versioning, bcrypt passwords, brute force lockout | Wede does not store ePHI - payloads are opaque and pass through encrypted. This significantly reduces the compliance surface for healthcare integrators. The 2025 proposed HIPAA Security Rule updates (expected final May 2026) make encryption at rest and in transit, MFA, and audit controls mandatory without exception. Wede meets all proposed requirements. ### Banking - CBUAE (UAE) For UAE licensed financial institutions (LFIs), Wede aligns with the CBUAE Operational Risk Regulation and Technology Risk Standards (Articles 12 and 13 of the CBUAE Rulebook): | CBUAE Requirement | Wede Implementation | | ----------------------------------------- | ----------------------------------------------------------------------- | | Business continuity plans | Offline-first SDK — critical functions maintained without internet | | Disaster recovery | Multi-channel fallback, automatic channel transition, zone monitoring | | Operational risk event notification (24h) | Immutable audit log with timestamp, exportable for regulatory reporting | | Technology risk management framework | Cryptographic traceability, integrity hash per event, RBAC | | IT governance and cyber resilience | TLS 1.2+, bcrypt, SHA-256, GCP Secret Manager, Cloud Run isolation | | Critical business function continuity | Offline queue with reconciliation — no data loss during outages | The CBUAE Operational Risk Regulation requires banks to notify the Central Bank within 24 hours of any event triggering business continuity plans. Wede's immutable audit trail with structured timestamps supports this reporting obligation. ### Government and Critical Infrastructure - NIS2 For government and infrastructure deployments: | NIS2 Requirement | Wede Implementation | | --------------------- | ---------------------------------------------------------------------------- | | Risk management | Multi-layer resilience, zone-level connectivity monitoring | | Incident handling | Structured lifecycle, webhook notifications, audit export | | Business continuity | Offline-first SDK, multi-channel fallback, data sync on reconnection | | Supply chain security | Private core repository, public SDK only - no proprietary algorithm exposure | | Access control | Cascading RBAC, session revocation, API key rotation | | Cryptography | TLS 1.2+, bcrypt, SHA-256, secrets in GCP Secret Manager | | Data residency | Configurable per country and per zone - EU by default | *** ## What Wede Does Not Do To be explicit about scope: * Wede does **not** store payload content - payloads are opaque * Wede does **not** provide MFA for end users - this is your responsibility at the application layer * Wede does **not** perform penetration testing on your integration - you are responsible for your own security posture * Wede does **not** guarantee anonymisation - if your payload contains PII, you are responsible for encrypting it before sending *** ## Security Contact To report a security vulnerability: [security@wede.pt](mailto:security@wede.pt) We respond to all security reports within 24 hours. We do not operate a public bug bounty programme at this time. # Sync Source: https://docs.wede.pt/concepts/sync How offline event batches are synchronised when connectivity is restored ## What is Sync? When a device operates offline, events are captured and queued locally. Once connectivity is restored, the Wede SDK submits these events as a batch to the platform for processing, deduplication and delivery. The sync mechanism ensures that no event is lost, regardless of how long the device was offline or which channel was used for transmission. ## How it works 1. Events are captured and stored locally with an `idempotency_key` 2. When connectivity is restored, the SDK submits a sync batch via `POST /v1/sync/batch` 3. Wede processes each event, checks idempotency keys and deduplicates 4. The platform confirms which events were accepted and which were rejected 5. Rejected events are returned with a reason - the integrator decides whether to retry ## Idempotency Every event must have a unique `idempotency_key`. This key is used to prevent duplicate processing if the same batch is submitted more than once - for example, if the network drops mid-submission. The key should be generated on the device before the event is captured, not at submission time. ```typescript theme={null} const event = { type: 'PAYMENT', idempotency_key: 'device-001-' + Date.now(), payload: { amount: 150.00, currency: 'EUR' } } ``` ## Batch submission ```typescript theme={null} import { WedeClient } from '@wede/sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY' }) const result = await client.syncBatch({ events: offlineQueue, device_id: 'device-001', captured_at: new Date().toISOString() }) console.log(`Accepted: ${result.data.accepted}, Rejected: ${result.data.rejected}`) ``` ## Checking sync status ```typescript theme={null} const status = await client.getSyncStatus(batchId) ``` ## Best practices * Generate `idempotency_key` at event capture time, not at submission * Keep batches under 500 events for optimal performance * Always check the `rejected` count and handle rejections * Use `device_id` consistently to correlate events from the same device * Submit batches as soon as connectivity is restored - do not accumulate indefinitely ## Channels Sync batches are always submitted via REST. Individual events captured offline may have been transmitted via structured protocols or other channels - sync consolidates them into a single REST call when connectivity allows. # Verticals Source: https://docs.wede.pt/concepts/verticals How Wede serves different industries ## Healthcare & Emergency Services In healthcare, communication failures cost lives. Wede ensures that emergency dispatch, patient monitoring alerts, and field medical team coordination continue even when hospital networks fail. **Use cases:** * Emergency medical dispatch and ambulance coordination * Patient status updates between facilities * ICU and critical care alerts * Field team coordination during mass casualty events * Medical supply chain and blood bank alerts * Rural and remote clinic connectivity **Example event:** ```json theme={null} { "type": "CARDIAC_ARREST_ALERT", "priority": "critical", "vertical": "healthcare", "payload": { "unit": "AMB-PT-07", "location": "Hospital Santa Maria, Lisboa", "eta_minutes": 4 } } ``` *** ## Banking & Financial Services Payment terminals, ATM networks, and field banking agents operate in environments where connectivity is unreliable. Wede ensures transaction continuity and field agent coordination regardless of network conditions. **Use cases:** * Payment terminal resilience * ATM network monitoring and alerts * Field agent dispatch and coordination * Fraud alert delivery * Mobile banking operations in low-connectivity areas * Cross-border transaction notifications **Example event:** ```json theme={null} { "type": "FRAUD_ALERT", "priority": "high", "vertical": "banking", "payload": { "terminal_id": "ATM-NG-042", "account_ref": "****4521", "amount": 150000, "currency": "NGN" } } ``` *** ## Logistics & Delivery Last-mile delivery operates in areas with poor connectivity. Wede keeps fleet coordination, delivery confirmation, and warehouse operations running continuously. **Use cases:** * Last-mile delivery coordination * Fleet management and driver dispatch * Warehouse operations and inventory alerts * Cold chain monitoring * Cross-border logistics coordination * Port and customs notifications **Example event:** ```json theme={null} { "type": "DELIVERY_CONFIRMED", "priority": "normal", "vertical": "delivery", "payload": { "driver_id": "DRV-KE-019", "order_id": "ORD-29841", "location": "Westlands, Nairobi" } } ``` *** ## Telecommunications Network operations and field engineer dispatch require reliable communication even when the network being maintained is itself degraded. **Use cases:** * Network operations centre alerts * Field engineer dispatch and coordination * Infrastructure fault notifications * Tower and base station monitoring * Service outage management * Customer impact alerts **Example event:** ```json theme={null} { "type": "NETWORK_FAULT", "priority": "high", "vertical": "telecom", "payload": { "site_id": "BTS-AE-112", "fault_type": "power_failure", "region": "Dubai — Al Barsha", "affected_subscribers": 8400 } } ``` *** ## Emergency Services Civil protection, fire brigades, and search and rescue teams operate in the most challenging connectivity environments. Wede is built for these conditions. **Use cases:** * Emergency dispatch coordination * Field team communication during incidents * Resource allocation and mutual aid * Evacuation order delivery * Incident command coordination * Cross-agency communication **Example event:** ```json theme={null} { "type": "EVACUATION_ORDER", "priority": "critical", "vertical": "events", "payload": { "zone": "zona_norte_maputo", "radius_km": 5, "reason": "industrial_incident", "population_affected": 12400 } } ``` *** ## Government & Public Services Critical infrastructure and public services require guaranteed operational continuity. Wede provides the resilience layer that keeps these services running. **Use cases:** * Border control operations * Utility network monitoring (water, electricity, gas) * Public transport coordination * Civil protection alerts * Infrastructure maintenance dispatch * Inter-agency emergency communication **Example event:** ```json theme={null} { "type": "INFRASTRUCTURE_ALERT", "priority": "high", "vertical": "gov", "payload": { "asset_id": "POWER-GRID-AO-07", "alert_type": "overload", "region": "Luanda Norte", "estimated_restoration": "2026-05-19T18:00:00Z" } } ``` # Zones Source: https://docs.wede.pt/concepts/zones How Wede organises operational coverage by geographic zone ## What is a Zone A zone is a geographic operational area, defined and managed by your tenant within your pre-agreed geographic coverage. Each zone has its own connectivity state, channel configuration, and incident tracking. Zones allow you to model the real-world structure of your operations - a hospital, a city district, a country region, or an entire country - and monitor each area independently. ## Zone Connectivity States Each zone operates in one of four connectivity states: | State | Meaning | | ------------- | --------------------------------------------------------------------------------------------- | | **online** | Full internet connectivity - primary channel active | | **degraded** | Reduced connectivity - optimised routing active | | **sms\_only** | Internet unavailable - structured protocols active, extended fallback engages automatically | | **offline** | All external channels unavailable - events queue locally with guaranteed sync on reconnection | State transitions are detected automatically by Wede based on real-time monitoring. Your integration does not need to handle state changes - Wede routes transparently. ## Zone Configuration Each zone has: * **Zone code** - unique identifier (e.g. `zone_hospital_evora`) * **Name** - human-readable label * **Country and region** - geographic scope * **GPS coordinates** - centre point for map display and proximity calculations * **Active verticals** - which industry modules are active in this zone * **Connectivity state** - current operational status * **Incident flag** - whether an active incident is in progress The number of zones you can create is limited by your plan. ## Creating a Zone Via the dashboard at [app.wede.pt/dashboard/zones](https://app.wede.pt/dashboard/zones) or via the API: ```bash theme={null} curl -X POST https://api.wede.pt/v1/tenant/zones \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "zone_code": "zone_hospital_evora", "name": "Hospital Espírito Santo — Évora", "country": "PT", "region": "Évora", "lat_center": 38.5687, "lng_center": -7.9038 }' ``` ## Listing Zones ```bash theme={null} curl https://api.wede.pt/v1/tenant/zones \ -H "x-wede-api-key: wede_live_YOUR_KEY" ``` Response: ```json theme={null} { "zones": [ { "zone_code": "zone_hospital_evora", "name": "Hospital Espírito Santo — Évora", "country": "PT", "connectivity_state": "online", "incident_active": false, "lat_center": "38.568700", "lng_center": "-7.903800" } ], "total": 1 } ``` ## Zone Examples by Vertical **Healthcare:** * `zone_hospital_lisbon` - Hospital Santa Maria, Lisboa * `zone_emergency_porto` - Emergency Centre, Porto * `zone_rural_kisumu` - Rural District Hospital, Kisumu **Banking:** * `zone_atm_network_lagos` - ATM Network, Lagos * `zone_branch_dubai` - Branch Operations, Dubai * `zone_field_agents_nairobi` - Field Agents, Nairobi **Logistics:** * `zone_warehouse_maputo` - Warehouse, Maputo * `zone_lastmile_singapore` - Last-Mile, Singapore * `zone_port_luanda` - Port Operations, Luanda **Government:** * `zone_border_control_pt` - Border Control, Portugal * `zone_utility_grid_ao` - Utility Grid, Angola ## Incidents A zone can have an active incident flag. When an incident is active: * Wede prioritises delivery through all available channels * Configured webhooks receive immediate notification * The dashboard displays the zone in alert state * All events for the zone are escalated in priority Incident state is visible in real-time in the dashboard and included in all zone API responses. ## Zone Visibility by Role | Role | Zone Access | | ------------------------ | ------------------------------------- | | `company_admin` | All zones in their tenant | | `company_tech` | All zones in their tenant | | `operational_supervisor` | All zones in their tenant | | `field_operator` | Assigned zones only | | `country_admin` | All zones in their assigned countries | # Banking & Fintech - Field Agent Dispatch Source: https://docs.wede.pt/examples/banking Complete integration example for field banking agent coordination with DORA compliance ## Overview This example covers field banking agent dispatch for mobile money and agent banking operations. An incident is reported (ATM fault, fraud alert, field agent request), the system scores available agents by proximity and capability, dispatches the best match, and tracks the mission to completion. Works fully offline - critical for agent banking in rural areas with degraded connectivity. *** ## 1. Submit a Field Incident ```typescript theme={null} import { WedeClient } from '@wede/sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY' }) const event = await client.sendEvent({ type: 'ATM_FAULT', priority: 'high', vertical: 'banking', idempotency_key: `atm-fault-${terminalId}-${Date.now()}`, zone_id: 'zone_lagos_island', payload: { terminal_id: 'ATM-NG-042', fault_type: 'cash_jam', location: { lat: 6.4550, lng: 3.3841 }, queue_length: 23, }, }) ``` *** ## 2. Score and Dispatch Field Agent ```typescript theme={null} // Score agents by proximity and capability const scored = await client.scoreTeams({ lat: 6.4550, lng: 3.3841, vertical: 'banking', priority: 'high', required_equipment: ['cash_cassette', 'engineer_kit'], }) const agent = scored.data.scored.find(t => t.recommended) // Dispatch await client.dispatch({ event_id: event.event_id, team_id: agent.team_id, event_lat: 6.4550, event_lng: 3.3841, notes: `ATM-NG-042 cash jam — ${agent.eta_min} min ETA`, }) ``` *** ## 3. Offline Agent App (React Native) Field agents in rural areas operate with degraded connectivity. The SDK queues all operations locally and syncs automatically. ```typescript theme={null} import AsyncStorage from '@react-native-async-storage/async-storage' import { WedeClient } from '@wede/react-native-sdk' const agentClient = new WedeClient({ apiKey: 'wede_live_AGENT_KEY', storage: AsyncStorage, }) // Accept mission — works offline const result = await agentClient.updateMissionStatus(missionId, 'ACK') if (result.queued) { console.log('Offline — queued for sync') } // En route — GPS update sent even without connectivity await agentClient.updateMemberLocation(teamId, memberId, 6.4612, 3.3905) await agentClient.updateMissionStatus(missionId, 'ON_ROUTE') // On site await agentClient.updateMissionStatus(missionId, 'ON_SITE') // Complete with structured feedback await agentClient.updateMissionStatus(missionId, 'COMPLETED', { resolution: 'cash_cassette_replaced', atm_operational: true, cash_loaded_ngn: 5000000, duration_min: 34, }) ``` *** ## 4. Fraud Alert Delivery For time-critical fraud alerts where internet may be unavailable: ```typescript theme={null} await client.sendEvent({ type: 'FRAUD_ALERT', priority: 'critical', vertical: 'banking', idempotency_key: `fraud-${accountRef}-${Date.now()}`, payload: { account_ref: '****4521', terminal_id: 'POS-AE-087', amount: 150000, currency: 'NGN', location: { lat: 6.4550, lng: 3.3841 }, }, }) ``` If internet is unavailable, Wede automatically routes via structured protocols - the payload is fragmented, transmitted, and reassembled at the destination without any changes to your code. *** ## 5. Annual Usage and Billing ```typescript theme={null} const billing = await client.getBilling() console.log(`Plan: ${billing.data.current_plan.display_name}`) console.log(`Events used: ${billing.data.usage.events_this_year} / ${billing.data.current_plan.max_events_per_year}`) console.log(`Dispatches: ${billing.data.usage.dispatches_total}`) ``` *** ## DORA Alignment | DORA Requirement | This Integration | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | ICT risk management | Multi-protocol fallback architecture, patent-pending technology, with tenant-defined channel priority and automatic sync on reconnection | | Operational continuity | Offline SDK - operations continue without internet | | Incident reporting | Immutable audit log, webhook notifications per event | | Data integrity | SHA-256 per event, idempotency key, reconciliation | | Access controls | RBAC per role, API key rotation, JWT revocation | | Third-party oversight | Full audit trail exportable, contractual SLAs available | | Resilience testing | Sandbox environment with connectivity simulation | # Delivery & Logistics - Driver Dispatch Source: https://docs.wede.pt/examples/delivery Complete integration example for last-mile delivery and ride-hailing with offline resilience ## Overview This example covers driver dispatch for delivery and ride-hailing operations. A service request arrives, the proximity engine finds the nearest available driver, dispatches them, and tracks the delivery to completion - all working offline when the driver loses connectivity. *** ## 1. Submit a Service Request ```typescript theme={null} import { WedeClient } from '@wede/sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY' }) const event = await client.sendEvent({ type: 'RIDE_REQUEST', priority: 'normal', vertical: 'delivery', idempotency_key: `ride-${customerId}-${Date.now()}`, zone_id: 'zone_maputo_central', payload: { customer_id: 'cust_29841', pickup: { lat: -25.9692, lng: 32.5732, address: 'Av. Julius Nyerere, Maputo' }, dropoff: { lat: -25.9012, lng: 32.5891, address: 'Aeroporto Internacional de Maputo' }, vehicle_type: 'standard', }, }) ``` *** ## 2. Score and Dispatch Nearest Driver ```typescript theme={null} const scored = await client.scoreTeams({ lat: -25.9692, lng: 32.5732, vertical: 'delivery', priority: 'normal', }) const driver = scored.data.scored.find(t => t.recommended) console.log(`${driver.team_name} — ${driver.distance_km} km — ETA ${driver.eta_min} min`) await client.dispatch({ event_id: event.event_id, team_id: driver.team_id, event_lat: -25.9692, event_lng: 32.5732, notes: `Pickup: Av. Julius Nyerere — Dropoff: Aeroporto`, }) ``` *** ## 3. Driver App - Offline-First (React Native) ```typescript theme={null} import AsyncStorage from '@react-native-async-storage/async-storage' import { WedeClient } from '@wede/react-native-sdk' const driverClient = new WedeClient({ apiKey: 'wede_live_DRIVER_KEY', storage: AsyncStorage, }) // Accept ride — works even without internet const ack = await driverClient.updateMissionStatus(missionId, 'ACK') // Update GPS every 30s — queued offline if no connectivity setInterval(async () => { const pos = await getCurrentPosition() await driverClient.updateMemberLocation(teamId, memberId, pos.lat, pos.lng) }, 30000) // En route to pickup await driverClient.updateMissionStatus(missionId, 'ON_ROUTE') // Arrived at pickup await driverClient.updateMissionStatus(missionId, 'ON_SITE') // Trip complete with feedback await driverClient.updateMissionStatus(missionId, 'COMPLETED', { distance_km: 8.4, duration_min: 22, fare: 450, currency: 'MZN', rating_requested: true, }) // Flush any queued operations when connectivity restored const { flushed, failed } = await driverClient.flushQueue() console.log(`Synced ${flushed} operations`) ``` *** ## 4. Real-Time GPS Tracking The dashboard shows driver positions in real time. GPS coordinates are updated via `updateMemberLocation` and displayed on the operational map for supervisors. ```typescript theme={null} // Swift — iOS driver app let client = WedeClient(apiKey: "wede_live_DRIVER_KEY") // Update location try await client.updateMemberLocation( teamId: teamId, memberId: memberId, lat: location.coordinate.latitude, lng: location.coordinate.longitude ) ``` *** ## 5. Webhooks for Your Backend ```typescript theme={null} // Your backend receives real-time updates app.post('/webhooks/wede', (req, res) => { const { event, mission_id, status } = req.body if (event === 'mission.status_updated') { if (status === 'ON_ROUTE') notifyCustomer(mission_id, 'Driver on the way') if (status === 'ON_SITE') notifyCustomer(mission_id, 'Driver arrived') if (status === 'COMPLETED') finaliseTrip(mission_id) } res.sendStatus(200) }) ``` *** ## Offline Scenario - What Happens Driver enters a tunnel or rural area with no connectivity: 1. `updateMemberLocation` - queued locally in AsyncStorage 2. `updateMissionStatus('COMPLETED')` - queued locally 3. Connectivity restored - `flushQueue()` syncs all operations in order 4. Your webhook receives the events with original timestamps 5. Zero data loss, zero duplicates - idempotency key enforced No changes to your integration required. # Healthcare - Emergency Dispatch Source: https://docs.wede.pt/examples/healthcare Complete integration example for emergency medical dispatch with offline resilience ## Overview This example covers the complete workflow for emergency medical dispatch: a patient event arrives via the Wede API, the proximity engine scores available teams, the best team is dispatched, and the field operator updates the mission lifecycle in real time. The entire flow works offline. If the hospital network fails at any point, the SDK queues operations locally and syncs when connectivity is restored - without any changes to your integration. *** ## 1. Submit an Emergency Event ```typescript theme={null} import { WedeClient } from '@wede/sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY' }) const event = await client.sendEvent({ type: 'CARDIAC_ARREST', priority: 'critical', vertical: 'healthcare', idempotency_key: `cardiac-${Date.now()}-amb`, zone_id: 'zone_lisbon_norte', payload: { patient_age: 67, location: { lat: 38.7369, lng: -9.1395 }, symptoms: ['chest_pain', 'loss_of_consciousness'], bystander_cpr: true, }, }) console.log(event.event_id) // use for dispatch ``` The payload is opaque to Wede. Encrypt it before sending if it contains ePHI. Wede transports - it does not inspect. *** ## 2. Score Available Teams ```typescript theme={null} const scored = await client.scoreTeams({ lat: 38.7369, lng: -9.1395, vertical: 'healthcare', priority: 'critical', required_equipment: ['defibrillator', 'oxygen'], }) const recommended = scored.data.scored.find(t => t.recommended) console.log(`${recommended.team_name} — ${recommended.distance_km} km — ETA ${recommended.eta_min} min`) ``` The score engine considers: GPS distance (haversine), equipment match, member availability, vertical capability, and zone geofence. The same algorithm runs offline in the SDK. *** ## 3. Dispatch the Team ```typescript theme={null} const dispatch = await client.dispatch({ event_id: event.event_id, team_id: recommended.team_id, event_lat: 38.7369, event_lng: -9.1395, notes: 'Cardiac arrest — bystander CPR in progress', }) ``` This triggers the `team.dispatched` webhook and creates a mission in `CREATED` status. *** ## 4. Field Operator - Mission Lifecycle (React Native) ```typescript theme={null} import AsyncStorage from '@react-native-async-storage/async-storage' import { WedeClient } from '@wede/react-native-sdk' const fieldClient = new WedeClient({ apiKey: 'wede_live_FIELD_KEY', storage: AsyncStorage, // enables offline queue }) // Load assigned missions const missions = await fieldClient.listMissions({ status: 'SENT' }) const mission = missions.data.data[0] // Acknowledge await fieldClient.updateMissionStatus(mission.id, 'ACK') // En route await fieldClient.updateMissionStatus(mission.id, 'ON_ROUTE') // On site — works offline, syncs automatically const result = await fieldClient.updateMissionStatus(mission.id, 'ON_SITE') if (result.queued) { console.log('Offline — status queued, will sync on reconnection') } // Complete with feedback await fieldClient.updateMissionStatus(mission.id, 'COMPLETED', { patient_stable: true, intervention: 'defibrillation', transport_to: 'Hospital Santa Maria', on_site_duration_min: 12, }) ``` *** ## 5. Webhooks - Real-Time Notifications Configure a webhook to receive mission lifecycle events: ```bash theme={null} curl -X POST https://api.wede.pt/v1/webhooks \ -H "X-Wede-API-Key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-system.com/webhooks/wede", "events": ["mission.created", "mission.status_updated", "team.dispatched"], "secret": "your-hmac-secret" }' ``` Payload example for `mission.status_updated`: ```json theme={null} { "event": "mission.status_updated", "mission_id": "uuid", "team_id": "uuid", "status": "ON_SITE", "timestamp": "2026-05-27T14:23:11Z" } ``` *** ## HIPAA Alignment | Requirement | This Integration | | --------------------- | ----------------------------------------------------------------- | | Access Controls | API key scoped to tenant, RBAC enforced per role | | Audit Controls | Every operation logged with user, IP, timestamp | | Integrity Controls | SHA-256 per event, idempotency key enforced | | Transmission Security | TLS 1.2+ enforced, no unencrypted fallback | | Payload Privacy | ePHI encrypted by integrator before sending - Wede never reads it | # Wede Technology Source: https://docs.wede.pt/index Operational continuity platform for mission-critical services - works without internet ## The Problem Every day, critical operations fail because of internet connectivity. Emergency dispatch loses contact with field teams. Hospital systems go offline during power outages. Banking terminals stop working when the network drops. The world depends on connectivity - but connectivity is not guaranteed. ## The Solution Wede is an **operational continuity platform** that keeps mission-critical services running regardless of internet availability. When connectivity degrades, Wede switches automatically to the next available channel - transparently, without any changes to your integration, without interrupting your operations. Whoever is on either end, a dispatcher, a field team, or your own end customer, keeps working. Your systems keep running. ## Who Uses Wede Wede's architecture is vertical-agnostic and region-agnostic by design, built to run any operational vertical, anywhere in the world. Today it powers organisations where downtime is not an option: * **Healthcare & Emergency Services** - emergency dispatch, patient monitoring, field medical teams, ambulance coordination * **Banking & Financial Services** - payment terminals, ATM networks, field agents, fraud alerts * **Logistics & Delivery** - last-mile coordination, fleet management, warehouse operations * **Telecommunications** - network operations, field engineer dispatch, infrastructure monitoring * **Government & Public Services** - critical infrastructure, border control, utilities, civil protection Wede's architecture is not limited to these sectors. The same offline-first, multi-protocol foundation applies anywhere operational continuity cannot depend on internet access, industrial and IoT hardware monitoring, defence and critical infrastructure, agriculture and rural supply chains, maritime and offshore operations, humanitarian and disaster response. If your operations cannot stop when the network does, Wede is built for it. ## Communication Channels Wede routes events through multiple channels, automatically selecting the best available option per zone: | Channel | Description | | ------------------------ | ------------------------------------------------------------- | | **REST Full** | Standard internet, primary channel | | **REST Compressed** | Optimised internet, low-bandwidth environments | | **Structured Protocols** | Compact structured transmission, when internet is unavailable | | **Voice** | Voice call delivery, for critical alerts | | **LoRa** | Long-range IoT, remote and rural areas | | **Satellite** | Global satellite coverage, extreme environments | | **Edge** | Local edge processing, zero external dependency | Wede's multi-protocol fallback architecture is proprietary, patent-pending technology, built and extended continuously. Rather than a single fixed hierarchy, each tenant defines its own path and priority across channels, choosing between a lighter store-and-forward mode or a full automatic cascade. Whichever mode you choose, every queued operation synchronises automatically, with guaranteed integrity, the moment connectivity returns. ## How It Works Wede integrates with your existing systems via a simple REST API. You send events - Wede ensures they are delivered. Behind the scenes, Wede monitors connectivity across your operational zones and routes each event through the best available channel. If internet is unavailable, delivery continues through alternative channels until connectivity is restored. Your integration stays the same. Wede handles the rest. ## Get Started ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "EMERGENCY_DISPATCH", "priority": "critical", "vertical": "healthcare", "idempotency_key": "evt-001", "payload": { "unit": "AMB-PT-07", "location": "Hospital Santa Maria, Lisboa" } }' ``` [Try the demo](https://app.wede.pt/register) · [Read the Quickstart](/quickstart) · [API Reference](/api-reference/introduction) ## Base URL All API requests are made over HTTPS. The platform is hosted in Europe (GCP europe-west1) with global reach across 190+ countries. # Quickstart Source: https://docs.wede.pt/quickstart Send your first event in under 5 minutes ## Before you start You need a Wede account and an API key. [Sign up at app.wede.pt](https://app.wede.pt/register) or contact [support@wede.pt](mailto:support@wede.pt) to get access. Your API key looks like this: `wede_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` *** ## Step 1 — Send your first event Events represent operational incidents requiring a team response. Choose your industry: ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "EMERGENCY", "priority": "high", "vertical": "healthcare", "idempotency_key": "hc-evt-001", "payload": { "condition": "cardiac_arrest" }, "location": { "lat": 38.7169, "lng": -9.1395 } }' ``` ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "DISPATCH", "priority": "high", "vertical": "banking", "idempotency_key": "bk-evt-001", "payload": { "terminal_id": "ATM-042", "issue": "offline" }, "location": { "lat": 25.2048, "lng": 55.2708 } }' ``` ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "STATUS_UPDATE", "priority": "normal", "vertical": "logistics", "idempotency_key": "lg-evt-001", "payload": { "driver_id": "DRV-019", "status": "incident" }, "location": { "lat": -1.2921, "lng": 36.8219 } }' ``` ```bash theme={null} curl -X POST https://api.wede.pt/v1/events \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "EMERGENCY", "priority": "high", "vertical": "telecom", "idempotency_key": "tc-evt-001", "payload": { "site_id": "BTS-AE-112", "alert": "power_failure" }, "location": { "lat": 25.1972, "lng": 55.2744 } }' ``` Response: ```json theme={null} { "event_id": "fbea1e0d-8f6b-42f5-bf9b-58fe77430f53", "status": "pending", "channel_selected": "rest_full", "estimated_delivery_ms": 250 } ``` The event is now `pending` — awaiting dispatch to a team. *** ## Step 2 — Score and dispatch a team Score available teams by proximity and capability, then dispatch the best match: ```bash theme={null} # Score teams for the event location curl -X POST https://api.wede.pt/v1/teams/dispatch/score \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "lat": 38.7169, "lng": -9.1395, "vertical": "healthcare", "priority": "high" }' ``` ```bash theme={null} # Dispatch the top-scored team curl -X POST https://api.wede.pt/v1/teams/dispatch \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "event_id": "fbea1e0d-8f6b-42f5-bf9b-58fe77430f53", "team_id": "259edc6e-95f3-42ba-bac5-263cfe51ebc0", "event_lat": 38.7169, "event_lng": -9.1395, "notes": "Patient is conscious, use south entrance" }' ``` This creates a mission and notifies the team. The team then updates their status as they progress: `ACK → ON_ROUTE → ON_SITE → COMPLETED`. *** ## Step 3 — Set up a webhook Receive real-time notifications when missions progress: ```bash theme={null} curl -X POST https://api.wede.pt/v1/webhooks \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-system.com/wede-webhook", "events": ["team.dispatched", "mission.status_updated"] }' ``` *** ## Step 4 — Enable auto-dispatch (optional) Let Wede automatically dispatch the best team when an event arrives: ```bash theme={null} curl -X PATCH https://api.wede.pt/v1/tenant/dispatch-settings \ -H "x-wede-api-key: wede_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "dispatch_mode": true, "dispatch_threshold": 0.20, "reinforcement_timeout_min": 10 }' ``` With auto-dispatch enabled, the flow is fully automatic: event arrives → best team scored → dispatched → mission created. *** ## What happens when connectivity fails Wede is offline-first. When internet is unavailable: 1. The SDK queues the dispatch locally with a sequence number 2. The local score engine selects the best team from cached data 3. When connectivity is restored, the queue syncs automatically 4. The server processes queued dispatches in order, idempotently Your integration does not change — Wede handles routing transparently. *** ## Next steps How Wede keeps operations running without internet JS, React Native, Android, Swift, Python Full endpoint documentation Healthcare, banking, logistics, telecom, emergency # SDKs Source: https://docs.wede.pt/sdks/overview Official Wede SDKs and client libraries ## Overview Wede provides five official SDKs covering all major platforms. Every SDK includes the full offline-first stack: local score engine, team cache, and persistent dispatch queue. | SDK | Repository | Language | | ----------------------- | ------------------------------------------------------------------------------------- | ---------- | | JavaScript / TypeScript | [Wedeadmin/wede-sdk-js](https://github.com/Wedeadmin/wede-sdk-js) | TypeScript | | React Native | [Wedeadmin/wede-sdk-react-native](https://github.com/Wedeadmin/wede-sdk-react-native) | TypeScript | | Android | [Wedeadmin/wede-sdk-android](https://github.com/Wedeadmin/wede-sdk-android) | Kotlin | | iOS / macOS | [Wedeadmin/wede-sdk-swift](https://github.com/Wedeadmin/wede-sdk-swift) | Swift | | Python | [Wedeadmin/wede-sdk-python](https://github.com/Wedeadmin/wede-sdk-python) | Python | *** ## JavaScript / TypeScript ### Installation ```bash theme={null} npm install @wede/sdk ``` ### Quick Start ```typescript theme={null} import { WedeClient } from '@wede/sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY' }) // Send an event const event = await client.sendEvent({ type: 'EMERGENCY', priority: 'high', vertical: 'healthcare', idempotency_key: crypto.randomUUID(), payload: { condition: 'cardiac_arrest' }, location: { lat: 38.7169, lng: -9.1395 } }) // Score and dispatch teams const scored = await client.scoreTeams({ lat: 38.7169, lng: -9.1395, vertical: 'healthcare', priority: 'high' }) await client.dispatch({ event_id: event.data.event_id, team_id: scored.data[0].team_id, event_lat: 38.7169, event_lng: -9.1395 }) ``` ### Offline Operation ```typescript theme={null} import { WedeClient, WedeCache, WedeOfflineDispatch, WedeDeviceId } from '@wede/sdk' // Generate permanent device ID on first install const deviceId = await WedeDeviceId.getOrCreate(storage) await client.registerDevice(deviceId, 'web', '2.0.0') // Offline dispatch — uses local score engine, queues if no connectivity const result = await offline.dispatch('cardiac_arrest', { lat: 38.7169, lng: -9.1395, vertical: 'healthcare' }) // result.queued === true when offline // Sync when connectivity restored await client.syncDeviceQueue(deviceId) ``` *** ## React Native ### Installation ```bash theme={null} npm install @wede/react-native-sdk npm install @react-native-async-storage/async-storage ``` ### Quick Start ```typescript theme={null} import AsyncStorage from '@react-native-async-storage/async-storage' import { WedeClient } from '@wede/react-native-sdk' const client = new WedeClient({ apiKey: 'wede_live_YOUR_KEY', storage: AsyncStorage, }) // Works online and offline const result = await client.dispatch({ event_id: 'uuid', team_id: 'uuid', event_lat: 38.7169, event_lng: -9.1395 }) // Request backup for active mission await client.requestBackup({ mission_id: 'uuid', event_id: 'uuid', event_lat: 38.7169, event_lng: -9.1395 }) ``` *** ## Android (Kotlin) ### Installation Add to `build.gradle.kts`: ```kotlin theme={null} dependencies { implementation("pt.wede.sdk:wede-sdk-android:1.2.0") } ``` ### Quick Start ```kotlin theme={null} import pt.wede.sdk.core.WedeClient import pt.wede.sdk.sync.WedeDeviceId val client = WedeClient( apiKey = "wede_live_YOUR_KEY", storage = SharedPreferencesStorage(context) ) // Generate permanent device ID val deviceId = WedeDeviceId.getOrCreate(storage) client.registerDevice(deviceId, "android", "2.0.0") // Dispatch (online or offline) client.dispatch(eventId = "uuid", teamId = "uuid", eventLat = 38.7169, eventLng = -9.1395) // Request backup client.requestBackup( missionId = "uuid", eventId = "uuid", eventLat = 38.7169, eventLng = -9.1395 ) // Sync when back online client.syncDeviceQueue(deviceId) ``` *** ## iOS / macOS (Swift) ### Installation Add to `Package.swift`: ```swift theme={null} dependencies: [ .package(url: "https://github.com/Wedeadmin/wede-sdk-swift.git", from: "1.2.0") ] ``` Supports iOS 15+ and macOS 12+. ### Quick Start ```swift theme={null} import WedeSDK let client = WedeClient(apiKey: "wede_live_YOUR_KEY") // Register device let deviceId = WedeDeviceId.getOrCreate() try await client.registerDevice(deviceId: deviceId, platform: "ios", appVersion: "2.0.0") // Score teams let scored = try await client.scoreTeams(lat: 38.7169, lng: -9.1395, vertical: "healthcare", priority: "high") // Dispatch try await client.dispatch(eventId: "uuid", teamId: scored.data[0].teamId, eventLat: 38.7169, eventLng: -9.1395) // Request backup try await client.requestBackup(missionId: "uuid", eventId: "uuid", eventLat: 38.7169, eventLng: -9.1395) // Sync try await client.syncDeviceQueue(deviceId: deviceId) ``` *** ## Python ### Installation ```bash theme={null} pip install wede-sdk ``` ### Quick Start ```python theme={null} from wede import WedeClient client = WedeClient(api_key="wede_live_YOUR_KEY") # Send event result = client.send_event( type="EMERGENCY", priority="high", vertical="healthcare", idempotency_key="evt-001", payload={"condition": "cardiac_arrest"}, location={"lat": 38.7169, "lng": -9.1395} ) # Score and dispatch scored = client.score_teams(lat=38.7169, lng=-9.1395, vertical="healthcare") client.dispatch(event_id=result["event_id"], team_id=scored["data"][0]["team_id"]) # Request backup client.request_backup( mission_id="uuid", event_id="uuid", event_lat=38.7169, event_lng=-9.1395 ) # Update dispatch settings client.update_dispatch_settings( dispatch_mode=True, dispatch_threshold=0.20, reinforcement_timeout_min=10 ) ``` *** ## Method Reference — All SDKs | Method | JS/TS | Python | React Native | Swift | Android | | ------------------------ | ------------------------ | -------------------------- | ------------------------ | ------------------------ | ------------------------ | | **Events** | | | | | | | Send event | `sendEvent` | `send_event` | `sendEvent` | `sendEvent` | `sendEvent` | | List events | `listEvents` | `list_events` | `listEvents` | `listEvents` | `listEvents` | | **Teams & Dispatch** | | | | | | | List teams | `listTeams` | `list_teams` | `listTeams` | `listTeams` | `listTeams` | | Score teams | `scoreTeams` | `score_teams` | `scoreTeams` | `scoreTeams` | `scoreTeams` | | Dispatch | `dispatch` | `dispatch` | `dispatch` | `dispatch` | `dispatch` | | Request backup | `requestBackup` | `request_backup` | `requestBackup` | `requestBackup` | `requestBackup` | | Update dispatch settings | `updateDispatchSettings` | `update_dispatch_settings` | `updateDispatchSettings` | `updateDispatchSettings` | `updateDispatchSettings` | | **Missions** | | | | | | | List missions | `listMissions` | `list_missions` | `listMissions` | `listMissions` | — | | Get mission | `getMission` | `get_mission` | `getMission` | `getMission` | — | | Update status | `updateMissionStatus` | `update_mission_status` | `updateMissionStatus` | `updateMissionStatus` | — | | **Offline / Devices** | | | | | | | Register device | `registerDevice` | `register_device` | `registerDevice` | `registerDevice` | `registerDevice` | | Sync device queue | `syncDeviceQueue` | `sync_device_queue` | `syncDeviceQueue` | `syncDeviceQueue` | `syncDeviceQueue` | | Refresh cache | `refreshCache` | `refresh_cache` | `refreshCache` | `refreshCache` | `refreshCache` | | **Tenant** | | | | | | | Get tenant info | `getTenantInfo` | `get_tenant_info` | `getTenantInfo` | `getTenantInfo` | — | | Get usage | `getUsage` | `get_usage` | `getUsage` | `getUsage` | — | | **Other** | | | | | | | List zones | `listZones` | `list_zones` | `listZones` | `listZones` | — | | List parsers | `listParsers` | `list_parsers` | `listParsers` | `listParsers` | — | | Get billing | `getBilling` | `get_billing` | `getBilling` | `getBilling` | — | | List webhooks | `listWebhooks` | `list_webhooks` | `listWebhooks` | — | — | | Create webhook | `createWebhook` | `create_webhook` | `createWebhook` | — | — | *** ## Support Email [support@wede.pt](mailto:support@wede.pt) or visit [docs.wede.pt](https://docs.wede.pt).