Autka's backend runs on Cloudflare Workers with a D1 SQL database and R2 object storage. It aggregates authorized car listing feeds and exposes a clean REST API for the Android app. This page documents the available endpoints, request parameters, and the CarOffer data model.
Base URL#
- Production: configured in the Android release build (
BACKEND_BASE_URLbuild config field) - Local development:
http://10.0.2.2:8787/(emulator loopback to host runningwrangler dev)
Endpoints#
GET /health#
Returns a simple liveness check for the Worker.
Response:
GET /offers#
Search and list offers. Query parameters mirror the app's SearchFilter fields.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
| query | string | Free-text search |
| make | string | Vehicle manufacturer filter |
| model | string | Vehicle model filter |
| minPrice | number | Requested minimum price; currently applied client-side after currency conversion |
| maxPrice | number | Requested maximum price; currently applied client-side after currency conversion |
| minYear | number | Minimum model year |
| maxYear | number | Maximum model year |
| maxMileageKm | number | Maximum odometer reading in kilometres |
| fuelTypes | string | Comma-separated fuel types |
| transmissions | string | Comma-separated transmission types |
| regions | string | Comma-separated regions |
| sources | string | Comma-separated source identifiers |
| sort | string | NEWEST, PRICE_ASC, PRICE_DESC, MILEAGE_ASC, or YEAR_DESC; price sorts are currently applied client-side |
| dedup | boolean | Set false to disable backend de-duplication |
| complete | boolean | Return the full matching set without pagination |
| limit | number | Page size (ignored when complete=true) |
| offset | number | Page offset (ignored when complete=true) |
Response (regular mode):
Response (complete=true): Returns the full matching set from one SQL statement, ignoring limit and offset. This prevents page shifts during ingestion. Complete responses are capped at 5,000 rows. If the result exceeds this limit, the API returns HTTP 422 instead of silently truncating.
Server-side price filtering and sorting are disabled until a normalized-price column is added. Android requests complete=true and performs these operations locally after currency conversion.
GET /offers/:id#
Returns a single offer by its namespaced CarOffer.id, for example otomoto:12345. The backend looks up the same offers.id value returned in list responses.
Response: CarOffer object.
The current Android client reads offer details directly from the Room cache rather than through this endpoint, so the UI stays consistent with the cached catalogue.
GET /sources#
Returns the list of configured sources with public-safe health metadata.
Response fields per source:
| Field | Type | Description |
|---|---|---|
| id | string | Source identifier |
| enabled | boolean | Whether the source is active |
| offerCount | number | null | Number of offers from this source |
| lastCompletedAtEpochMs | number | null | Timestamp of last completed ingest |
| lastCompletedOk | boolean | null | Whether the last completed ingest succeeded |
| lastOffersUpserted | number | null | How many offers were upserted in the last run |
If D1 health lookup fails, the static source list and enabled flags are still returned with health fields set to null. Raw ingestion errors remain server-side.
POST /admin/ingest#
Manually triggers ingestion. Requires a bearer token in the Authorization header.
Headers:
Behavior: Runs all enabled ingestion adapters. Concurrent scheduled or manual runs for the same source are skipped; different sources still run in parallel.
GET /images/:key#
Streams a cached offer image from R2.
Features:
- Supports ETag and HTTP 304 caching
- Never fetches arbitrary URLs on demand
- Returns the original URL if the image was not cached in R2
GET /import-services#
Returns a directory of import and logistics companies, optionally filtered by region.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
| region | string | Optional region filter |
CarOffer model#
The CarOffer shape in backend/src/lib/types.ts mirrors Android's com.autka.core.model.CarOffer. Keep them in sync when making changes.
Core fields:
| Field | Type | Description |
|---|---|---|
| sourceId | string | Source identifier |
| id | string | Stable namespaced offer ID (source:native-id) |
| title | string | Listing title |
| make | string | Vehicle manufacturer |
| model | string | Vehicle model |
| price | number | Listed price |
| currency | string | Price currency: PLN, EUR, or USD |
| fuel | string | Fuel type |
| transmission | string | Transmission type |
| region | string | Geographic region |
| originalUrl | string | Link to original marketplace listing |
| year | number | null | Model year (optional) |
| mileage | number | null | Odometer reading (optional) |
| power | number | null | Engine power (optional) |
| location | string | null | Location description (optional) |
| latitude | number | null | Latitude for map view (optional) |
| longitude | number | null | Longitude for map view (optional) |
| images | string[] | Image URLs (may be empty) |
| thumbnail | string | null | Thumbnail URL (optional) |
| updatedAt | string | null | ISO 8601 timestamp (optional) |
| expiresAt | string | null | ISO 8601 expiry timestamp (optional) |
Local development#
Install dependencies
Apply local migrations
Start the development server
Run tests and type checking
The Android debug build points at http://10.0.2.2:8787/ automatically.
Deploy to production#
Migration is required to create the offer schema, de-duplication columns, coordinate support, ingest leases, and to remove mock rows left by older deployments.
Set ENABLE_MOCK_SOURCE=true locally for demo data. Production keeps this disabled.