Files
synq/docs/api.md
2026-05-17 15:59:43 -04:00

178 lines
2.8 KiB
Markdown

# api contract
base url example:
```text
http://jeeves.mother:8765
```
all write endpoints require:
```text
authorization: bearer <phone_capture_token>
content-type: application/json
```
## get /health
request:
```http
GET /health
```
response:
```json
{
"ok": true,
"service": "synq",
"version": "0.1.0"
}
```
## post /capture
request:
```http
POST /capture
Authorization: Bearer <token>
Content-Type: application/json
```
body:
```json
{
"id": "phone-20260517-143122-a8f2",
"created_at": "2026-05-17T14:31:22-04:00",
"kind": "todo",
"body": "buy printer paper",
"tags": ["home", "errands"],
"device": "android"
}
```
field rules:
- `id`: required, stable, unique per capture.
- `created_at`: required iso-8601 datetime with timezone.
- `kind`: required, either `note` or `todo`.
- `body`: required, trimmed, non-empty.
- `tags`: required array, may be empty.
- `device`: required string, e.g. `android`.
success, newly accepted:
```json
{
"ok": true,
"status": "accepted",
"id": "phone-20260517-143122-a8f2"
}
```
success, duplicate/idempotent retry:
```json
{
"ok": true,
"status": "already_seen",
"id": "phone-20260517-143122-a8f2"
}
```
invalid token:
```json
{
"detail": "unauthorized"
}
```
invalid payload:
```json
{
"detail": "body must not be empty"
}
```
## org formatting rules
todo capture:
```org
* TODO buy printer paper :home:errands:
:PROPERTIES:
:CREATED: [2026-05-17 sun 14:31]
:SOURCE: android
:ID: phone-20260517-143122-a8f2
:END:
```
note capture:
```org
* note :retcon:
:PROPERTIES:
:CREATED: [2026-05-17 sun 14:33]
:SOURCE: android
:ID: phone-20260517-143322-b91c
:END:
mobile capture should stay dumb and append-only.
```
multiline note capture:
input body:
```text
retcon capture idea
phone should produce records, not edit org files.
```
output:
```org
* note: retcon capture idea :retcon:
:PROPERTIES:
:CREATED: [2026-05-17 sun 14:33]
:SOURCE: android
:ID: phone-20260517-143322-b91c
:END:
retcon capture idea
phone should produce records, not edit org files.
```
suggested behavior: use first line as heading suffix for notes when helpful, but preserve full body below the drawer.
## idempotency
server must never append the same `id` twice.
recommended implementation:
1. begin sqlite transaction.
2. check whether id already exists.
3. if exists, return `already_seen`.
4. append org entry.
5. insert id into sqlite.
6. commit.
if append succeeds but sqlite insert fails, log loudly. safest implementation may insert first inside a transaction and mark appended after write, but keep the code simple and test the duplicate path.
## status codes
- 200: accepted or already seen.
- 400: malformed request or invalid capture.
- 401: missing/invalid token.
- 500: server failed to append or persist state.
android should treat `accepted` and `already_seen` as synced.