A frontend reference for authentication, event ingestion, request payloads, headers, response shapes, and common integration pitfalls.
Version
v1.0
Auth
JWT Bearer
This page mirrors the public API documentation inside the frontend so users do not need Swagger or source access to understand the integration surface.
https://iot.pestscan.eu as the root for every API call.Authorization header.pco-id request header.Step 1
Review endpoints
Confirm the base URL, public routes, and which calls require authentication.
Step 2
Authenticate
Call Login first, then keep the returned refresh token available for token renewal.
Step 3
Send events
Use the Bearer token and include the required pco-id header for event ingestion.
The currently documented public endpoints are summarized below.
API Base URL
https://iot.pestscan.eu
The API uses JWT access tokens plus refresh tokens.
POST /Authentication/Login with username and password.accessToken and refreshToken.Authorization: Bearer <access_token> to protected endpoints.POST /Authentication/Refresh when the access token expires.Authorization: Bearer <access_token>Request body
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"username": "user@example.com",
"password": "your-password"
}
}Success response
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-02-19T13:45:00Z",
"body": {
"accessToken": "<jwt-access-token>",
"refreshToken": "<jwt-refresh-token>"
},
"is_successful": true
}Common error
{
"message_id": "...",
"date": "...",
"is_successful": false,
"error": {
"message": "Username or password incorrect.",
"code": "1",
"details": "The username or password provided is incorrect."
}
}cURL
curl -X POST "https://iot.pestscan.eu/api/v1.0/Authentication/Login" \
-H "Content-Type: application/json" \
-d '{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"username": "user@example.com",
"password": "your-password"
}
}'Python requests
import requests
payload = {
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"username": "user@example.com",
"password": "your-password",
},
}
response = requests.post(
"https://iot.pestscan.eu/api/v1.0/Authentication/Login",
json=payload,
)
data = response.json()JavaScript fetch
const response = await fetch("https://iot.pestscan.eu/api/v1.0/Authentication/Login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message_id: "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
date: "2026-03-11T12:32:33.994Z",
body: {
username: "user@example.com",
password: "your-password",
},
}),
});
const data = await response.json();C# HttpClient
using System.Net.Http.Headers;
using System.Text;
var client = new HttpClient();
var payload = """
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"username": "user@example.com",
"password": "your-password"
}
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://iot.pestscan.eu/api/v1.0/Authentication/Login", content);
var body = await response.Content.ReadAsStringAsync();The username value should be the user's email address.
Usernames are normalized to lowercase during login.
Unverified users are rejected and can return error code 2.
Request body
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"accessToken": "<previous-access-token>",
"refreshToken": "<current-refresh-token>"
}
}Success response
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-02-19T13:45:00Z",
"body": {
"accessToken": "<jwt-access-token>",
"refreshToken": "<jwt-refresh-token>"
},
"is_successful": true
}Common error
{
"message_id": "...",
"date": "...",
"is_successful": false,
"error": {
"message": "Wrong username or refreshToken.",
"code": "3",
"details": "The username or refresh token provided is incorrect."
}
}cURL
curl -X POST "https://iot.pestscan.eu/api/v1.0/Authentication/Refresh" \
-H "Content-Type: application/json" \
-d '{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"accessToken": "<previous-access-token>",
"refreshToken": "<current-refresh-token>"
}
}'Python requests
import requests
payload = {
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"accessToken": "<previous-access-token>",
"refreshToken": "<current-refresh-token>",
},
}
response = requests.post(
"https://iot.pestscan.eu/api/v1.0/Authentication/Refresh",
json=payload,
)
data = response.json()JavaScript fetch
const response = await fetch("https://iot.pestscan.eu/api/v1.0/Authentication/Refresh", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message_id: "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
date: "2026-03-11T12:32:33.994Z",
body: {
accessToken: "<previous-access-token>",
refreshToken: "<current-refresh-token>",
},
}),
});
const data = await response.json();C# HttpClient
using System.Text;
var client = new HttpClient();
var payload = """
{
"message_id": "f3a84b8d-9e54-4b89-9d95-c9348807e55d",
"date": "2026-03-11T12:32:33.994Z",
"body": {
"accessToken": "<previous-access-token>",
"refreshToken": "<current-refresh-token>"
}
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://iot.pestscan.eu/api/v1.0/Authentication/Refresh", content);
var body = await response.Content.ReadAsStringAsync();The refresh request does not require an Authorization header.
The access token and refresh token must belong to the same user context.
Use this section to understand event ingestion, required headers, payload structure, and expected responses.
These headers are required when sending new events to the ingestion endpoint.
When creating new events through POST /api/v1.0/Event, the request must include a pco-id header.
If pco-id is missing, the API returns 400 and the event will not be accepted.
pco-id: <pco_id>Authorization: Bearer <access_token>
pco-id: <pco_id>
Content-Type: application/jsonRoot: message_id, date, body, body.events
Per event: event_id, duid, event_type
date inside the event object is optional but recommended for realistic testing.
Minimal event request
{
"message_id": "8890fdf8-e31d-4c6a-80d0-84fee8b1627d",
"date": "2026-02-19T13:45:00Z",
"body": {
"events": [
{
"event_id": "evt-001",
"duid": "device-123",
"event_type": 901
}
]
}
}Full event example
{
"message_id": "c6d8e843-9789-4d8c-af18-3fe4fb0ef30f",
"date": "2026-02-19T13:45:00Z",
"body": {
"events": [
{
"event_id": "evt-001",
"duid": "device-123",
"vendor_code": "vendor-a",
"date": "2026-02-19T13:40:00Z",
"status": 1,
"battery_level": 91.5,
"signal_intensity": "-68dBm",
"event_type": 901,
"location_id": "loc-22",
"message": "Heartbeat",
"unknown_attributes": {
"any_key": "any_value"
}
}
]
}
}Success response
{
"message_id": "...",
"date": "...",
"body": {
"message": "Event(s) stored.",
"event": {
"message_id": "...",
"date": "...",
"body": {
"events": [
{
"event_id": "evt-001"
}
]
}
}
},
"is_successful": true
}cURL
curl -X POST "https://iot.pestscan.eu/api/v1.0/Event" \
-H "Authorization: Bearer <access_token>" \
-H "pco-id: <pco_id>" \
-H "Content-Type: application/json" \
-d '{
"message_id": "8890fdf8-e31d-4c6a-80d0-84fee8b1627d",
"date": "2026-02-19T13:45:00Z",
"body": {
"events": [
{
"event_id": "evt-001",
"duid": "device-123",
"event_type": 901
}
]
}
}'Python requests
import requests
payload = {
"message_id": "8890fdf8-e31d-4c6a-80d0-84fee8b1627d",
"date": "2026-02-19T13:45:00Z",
"body": {
"events": [
{
"event_id": "evt-001",
"duid": "device-123",
"event_type": 901,
}
]
},
}
response = requests.post(
"https://iot.pestscan.eu/api/v1.0/Event",
headers={
"Authorization": "Bearer <access_token>",
"pco-id": "<pco_id>",
},
json=payload,
)
data = response.json()JavaScript fetch
const response = await fetch("https://iot.pestscan.eu/api/v1.0/Event", {
method: "POST",
headers: {
Authorization: "Bearer <access_token>",
"pco-id": "<pco_id>",
"Content-Type": "application/json",
},
body: JSON.stringify({
message_id: "8890fdf8-e31d-4c6a-80d0-84fee8b1627d",
date: "2026-02-19T13:45:00Z",
body: {
events: [
{
event_id: "evt-001",
duid: "device-123",
event_type: 901,
},
],
},
}),
});
const data = await response.json();C# HttpClient
using System.Net.Http.Headers;
using System.Text;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "<access_token>");
client.DefaultRequestHeaders.Add("pco-id", "<pco_id>");
var payload = """
{
"message_id": "8890fdf8-e31d-4c6a-80d0-84fee8b1627d",
"date": "2026-02-19T13:45:00Z",
"body": {
"events": [
{
"event_id": "evt-001",
"duid": "device-123",
"event_type": 901
}
]
}
}
""";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://iot.pestscan.eu/api/v1.0/Event", content);
var body = await response.Content.ReadAsStringAsync();Error responses
These are the main non-success responses to expect when creating events.
pco-id header is omitted.{
"message_id": "...",
"date": "...",
"is_successful": false,
"error": {
"message": "PCO ID missing.",
"code": "1",
"details": "The required pco-id header was not provided."
}
}event_id has already been stored.{
"message_id": "...",
"date": "...",
"is_successful": false,
"error": {
"message": "Event already exists.",
"code": "2",
"details": "An event with the same event_id has already been stored."
}
}{
"message_id": "...",
"date": "...",
"is_successful": false,
"error": {
"message": "Event forwarding returned an error.",
"code": "200",
"details": "The event may already be stored even though the forwarding step failed."
}
}{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"request": [
"The request field is required."
],
"$.body.events[0].unknown_attributes": [
"The JSON value could not be converted to System.Text.Json.Nodes.JsonObject."
]
},
"traceId": "00-00000000000000000000000000000000-0000000000000000-00"
}Envelope fields
Event item fields
Reference values used across the API payloads and common attributes.
Event Types
Units of Measure (UOM)
Status Types
Molecules
These are the mistakes most likely to cause confusing 400 responses.
// example in request bodies.unknown_attributes to deserialize to a JSON object, not an array.event_id will trigger duplicate validation and return 400.