REST API¶
The app talks to the Part-DB server over a REST API in JSON-LD / Hydra format. Every request is authenticated with a Bearer token.
Authentication¶
Each request includes the header:
The token is read from Flutter Secure Storage every time the app starts. With OAuth login (Part-DB 2.15+) the access token is refreshed automatically before it expires; concurrent requests share a single refresh, and a 401 triggers one refresh-and-retry.
Every request sends Accept: application/ld+json. Plain application/json collections carry no pagination links, so the app would only ever see the first page.
Common parameters¶
| Parameter | Description |
|---|---|
itemsPerPage |
Maximum number of results per page (default 30 in Part-DB) |
hydra:view / view |
Pagination – contains hydra:next (next) with the path of the next page |
hydra:member / member |
Array of results in a collection response (both prefixed and unprefixed JSON-LD are supported) |
Timeouts¶
| Request type | Timeout |
|---|---|
| Standard (GET/PATCH) | 10 s |
| Attachment upload (POST) | 30 s |
Endpoints¶
Token verification¶
200 response:
Used by the Configuration screen to verify an API token. It only knows API tokens and answers 403 for OAuth tokens, so after an OAuth login the app checks access with GET /api/parts?itemsPerPage=1 and reads the username and granted scopes from the access token (a JWT: sub, scopes).
Search by IPN¶
Response:
Used when the scanned/typed code is exactly 7 digits.
Text search¶
GET /api/parts?name=%25{query}%25&itemsPerPage=100
GET /api/parts?ipn=%25{query}%25&itemsPerPage=100
GET /api/parts?manufacturer_product_number=%25{query}%25&itemsPerPage=100
GET /api/parts?description=%25{query}%25&itemsPerPage=100
Part-DB's LikeFilter matches exactly unless % wildcards are used, so the query is wrapped in %…%. The four requests run in parallel and the results are merged without duplicates (max 300 per field).
Search by parameter value¶
Collection responses contain parameter names only, and parameters have no collection endpoint. The "Value" search mode therefore reads GET /api/parts/{id} for parts with parameters and caches the values on the device, keyed by the part's lastModified. Only the first search (or parts changed since) costs extra requests.
Fetch all parts¶
The app follows hydra:view.hydra:next until it has collected every record. Used by the IPN Generator, the parameter search and the review screen.
The low-stock banner only fetches parts with a minimum stock set: GET /api/parts?minamount[gt]=0.
Part details¶
Response (excerpt):
{
"id": 42,
"name": "Resistor 10k",
"ipn": "1234567",
"minamount": 10,
"description": "...",
"comment": "...",
"category": "/api/categories/5",
"manufacturer": "/api/manufacturers/3",
"tags": "smd,resistor",
"partLots": [
{ "id": 7, "amount": 12.5, "instock_unknown": false, "comment": "", "storage_location": { "id": 2, "name": "Drawer A" } }
],
"parameters": [
{ "id": 101, "name": "Resistance", "value_typical": 10000, "value_text": "", "unit": "Ω" }
]
}
Note
Amounts are floats (meters, grams…) and are never rounded by the app. Lots with instock_unknown are excluded from the total and disable the low-stock warning.
Update a storage lot¶
PATCH /api/part_lots/{id}
Content-Type: application/merge-patch+json
{
"amount": 15,
"comment": "[2026-09-27] TME delivery\nprevious comment…",
"last_stocktake_at": "2026-09-27T10:00:00Z"
}
200 response: the updated PartLot object.
commentis sent only when the user typed a note: a dated line is prepended to the lot's existing comment (Part-DB's API has no way to attach a comment to the event log entry).last_stocktake_atis sent by Stock Taking for every counted lot, including those without a discrepancy.- The lot's
descriptionis never modified.
Update a parameter¶
The value is written back to the field it came from: value_text for text parameters, value_typical (a number) for single numeric values. Range parameters (value_min/value_max) are read-only in the app.
Assign an IPN¶
Fetch categories¶
The app fetches up to 200 categories, paging through hydra:next. Used by the Category browser.
Response (excerpt):
{
"hydra:member": [
{ "id": 1, "name": "Resistors", "parent": null },
{ "id": 2, "name": "SMD", "parent": "/api/categories/1" }
]
}
Fetch attachment types¶
Fetches the first available attachment type to use when uploading a photo.
Upload an attachment (photo)¶
POST /api/attachments
Content-Type: application/ld+json
Authorization: Bearer <token>
{
"name": "Photo - Resistor 10k",
"element": "/api/parts/42",
"attachment_type": "/api/attachment_types/1",
"upload": {
"data": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB...",
"filename": "Resistor_10k_1727430000000.jpg",
"private": false,
"becomePreviewIfEmpty": true
}
}
attachment_type is required by Part-DB; if no attachment type exists on the server, the upload is refused with a clear message.
201 response: the attachment object.
The photo is taken from the camera or gallery, compressed to JPEG and base64-encoded directly in the request body.
Error handling¶
The app parses error responses in the following order:
- The
hydra:descriptionfield - The
violations[].messagearray (validation errors) - The
detailfield - The HTTP status text
Errors are shown to the user through a SnackBar.