138 lines
3.3 KiB
Markdown
138 lines
3.3 KiB
Markdown
ID: DOC_000005 | Version: 0.2.2 | Status: Draft
|
||
Archived – superseded by new documentation.
|
||
By: Codex (GPT-5)
|
||
|
||
# Third-Party API Guide
|
||
|
||
## Purpose
|
||
This document explains how third-party services integrate with the Update Webservice: obtaining tokens, fetching manifests, downloading artifacts, and reporting status.
|
||
|
||
## Quick Start (First Client)
|
||
1) Request a pre-shared enrollment token from an admin/operator.
|
||
2) Enroll once to obtain a long-term token.
|
||
3) Store the long-term token locally and use it for all API calls.
|
||
|
||
## Base URLs
|
||
- Production: `https://update.wlkns.org`
|
||
- Staging: `https://staging.update.wlkns.org`
|
||
|
||
All endpoints are versioned under `/v1`.
|
||
|
||
## Authentication
|
||
All endpoints require `Authorization: Bearer <token>`.
|
||
|
||
### Enrollment (Pre-Shared Token -> Long-Term Token)
|
||
Clients obtain a long-term token by exchanging a pre-shared token provided by an admin/operator.
|
||
|
||
Request (example):
|
||
```
|
||
POST /v1/enroll
|
||
{
|
||
"project_id": "<project>",
|
||
"client_id": "<client>",
|
||
"software_id": "<software>",
|
||
"enroll_token": "<pre_shared_token>"
|
||
}
|
||
```
|
||
|
||
Response (example):
|
||
```
|
||
200 OK
|
||
{
|
||
"token": "<long_term_token>",
|
||
"scope": "read_manifest report_status",
|
||
"expires_at": "<iso8601 or null>"
|
||
}
|
||
```
|
||
|
||
Notes:
|
||
- Enrollment tokens are single-use and must be invalidated after a successful exchange.
|
||
- If the token is invalid or reused, the server responds with `unauthorized` or `invalid_payload`.
|
||
- Enrollment does not require an existing bearer token.
|
||
- If the client is already enrolled, the server responds with `already_enrolled` (HTTP 409).
|
||
|
||
## Client API (Read + Report)
|
||
|
||
### Get Manifest
|
||
```
|
||
GET /v1/projects/{project_id}/manifest
|
||
```
|
||
|
||
Response:
|
||
```
|
||
{
|
||
"version": "0.1.2",
|
||
"artifact_url": "https://update.wlkns.org/v1/projects/<project_id>/releases/0.1.2/artifact",
|
||
"sha256": "<hex>",
|
||
"sig_url": "<optional>"
|
||
}
|
||
```
|
||
|
||
Required scope: `read_manifest`
|
||
|
||
### Download Artifact
|
||
```
|
||
GET /v1/projects/{project_id}/releases/{version}/artifact
|
||
```
|
||
|
||
Required scope: `read_manifest`
|
||
|
||
### Report Status
|
||
```
|
||
POST /v1/projects/{project_id}/status
|
||
{
|
||
"project_id": "<project_id>",
|
||
"version": "<semver>",
|
||
"status": "success|failed|in_progress",
|
||
"timestamp": "<iso8601>",
|
||
"client_id": "<optional>",
|
||
"duration_ms": "<optional>",
|
||
"error_code": "<optional>"
|
||
}
|
||
```
|
||
|
||
Required scope: `report_status`
|
||
|
||
## Release API (Upload)
|
||
|
||
### Upload Release
|
||
```
|
||
POST /v1/projects/{project_id}/releases
|
||
Content-Type: multipart/form-data
|
||
```
|
||
|
||
Required scope: `upload_release`
|
||
|
||
Required fields:
|
||
- `version` (SemVer)
|
||
- `artifact` (file)
|
||
- `sha256` (hex)
|
||
|
||
Optional fields:
|
||
- `sig_url` or inline signature
|
||
- `key_id`
|
||
|
||
## Error Codes
|
||
Common error codes:
|
||
`unauthorized`, `rate_limited`, `not_found`, `invalid_payload`, `version_invalid`,
|
||
`version_exists`, `checksum_mismatch`, `signature_missing`, `signature_invalid`,
|
||
`payload_too_large`, `status_invalid`
|
||
|
||
## Rate Limits
|
||
Limits are tiered by scope. See `docs/architecture/openapi/paths/limits.yaml` for current values.
|
||
|
||
## Examples
|
||
Fetch manifest:
|
||
```
|
||
curl -H "Authorization: Bearer $TOKEN" \
|
||
https://update.wlkns.org/v1/projects/$PROJECT_ID/manifest
|
||
```
|
||
|
||
Report status:
|
||
```
|
||
curl -H "Authorization: Bearer $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"project_id":"'"$PROJECT_ID"'","version":"0.1.2","status":"success","timestamp":"2025-12-30T10:00:00Z"}' \
|
||
https://update.wlkns.org/v1/projects/$PROJECT_ID/status
|
||
```
|