You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> Version: `v1` (base path: `/api/v1/`), except `/api/health` which is unversioned for operational readiness. Google’s AIP recommends URI-segment versioning and keeping one GA “latest” at a time. ([aip.dev][1])
4
4
5
-
All responses are JSON.
5
+
All successful responses use `application/json` with a minimal envelope; all errors use `application/problem+json` per **RFC 9457** (which **obsoletes RFC 7807**). Servers **MUST** set the appropriate `Content-Type`. ([datatracker.ietf.org][2])
Error bodies follow RFC 9457; custom members are allowed for machine-readable details. ([rfc-editor.org][3])
26
+
27
+
## Versioning
28
+
29
+
Use `v1` as the base path and evolve compatibly; ship breaking changes as `v2`. Keep a single “latest” GA version; deprecate previews quickly. ([aip.dev][1])
30
+
31
+
## Media types & content negotiation
32
+
33
+
Clients SHOULD send `Accept: application/json`. The server MAY honor `+json` types via the structured syntax suffix (e.g., `application/problem+json`). If `Accept` excludes JSON, respond `406 Not Acceptable`. ([datatracker.ietf.org][4])
Use standard semantics: `200` for successful reads, `201` for creations, `401` for missing/invalid session, `403` for forbidden, `404` for not found, `415` for non-JSON request bodies, and `5xx` for server-side failures. ([rfc-editor.org][5])
24
38
25
-
* 200 OK – Successful read or non-creating action
26
-
* 201 Created – Resource created (e.g. submission)
27
-
* 401 Unauthorized – Missing/invalid `sid`
28
-
* 403 Forbidden – Authenticated but not allowed (e.g. not owner)
29
-
* 404 Not Found – Resource does not exist
30
-
* 415 Unsupported Media Type – JSON required
31
-
* 5xx – Server-side errors (prod only leaks generic message)
39
+
## Caching
40
+
41
+
Unless documented otherwise, endpoints return `Cache-Control: no-store` to avoid reuse of potentially stale representations (notably health, auth, and session-scoped reads). ([MDN Web Docs][6])
42
+
43
+
## Tracing
44
+
45
+
Requests may include `traceparent`. The server will echo the incoming value or generate a new one in **W3C Trace Context** format to support end-to-end correlation. ([W3C][7])
32
46
33
47
## Authentication
34
48
35
-
* Session cookie: `sid`
49
+
A session cookie named `sid` is set on successful login. Attributes: `HttpOnly; Path=/; SameSite=Lax; Max-Age=<env>` and `Secure` in production. Sign-in is restricted to `@studenti.unitn.it`. In development, the magic link is returned inline for convenience; in production, only a generic success is returned and the link is delivered by email. ([Google Cloud][8])
50
+
51
+
---
52
+
53
+
# Endpoints
36
54
37
-
* Attributes: `HttpOnly; Path=/; SameSite=Lax; Max-Age=<env>;` plus `Secure` in production
38
-
* Allowed email domain: `@studenti.unitn.it`
39
-
* In dev, magic link is returned in the response; in prod it is sent via email
55
+
## Health (unversioned)
56
+
57
+
### `GET /api/health`
58
+
59
+
Returns `200` with `{ "ok": true, "data": { "db": "ok" | "skipped", "time": <epoch> } }` when dependencies are reachable; otherwise `503` with a problem document. Always `Cache-Control: no-store`. If `Accept` excludes JSON (including all `+json` types), return `406` with a problem document. ([rfc-editor.org][5], [datatracker.ietf.org][4])
60
+
61
+
### `HEAD /api/health`
62
+
63
+
Returns `200` (healthy) or `503` (unhealthy) with no body; always `Cache-Control: no-store`. Rationale: an unversioned health path avoids breaking automation and aligns with operational probes that expect a stable URL. ([aip.dev][1])
40
64
41
65
---
42
66
43
67
## Auth
44
68
45
-
### POST `/auth/requestLink`
69
+
All request bodies MUST be `application/json`; otherwise return `415` with a problem document. ([rfc-editor.org][5])
Issues a one-time login token if the email domain is allowed. In development the `magicUrl` is returned; in production, the server sends mail and returns a generic success. ([Google Cloud][8])
92
+
93
+
### `GET /api/v1/auth/verify?token=…`
66
94
67
-
### GET `/auth/verify?token=...`
95
+
### `POST /api/v1/auth/verify`
68
96
69
-
* Input: `token` in query (or POST body)
70
-
* Output
97
+
Verifies a one-time token, upserts the user, establishes a session, and sets the `sid` cookie.
Use `403` for authenticated-but-forbidden access to other users’ resources. ([rfc-editor.org][5])
101
124
102
-
---
125
+
### `GET /api/v1/users/{slug}`
103
126
104
-
## Schools
127
+
Public, cache-negotiated read (ETag/If-None-Match supported by the handler), returning basic profile fields; `404` if not found. Slugs are stable, URL-safe identifiers intended for discovery and navigation. ([aip.dev][1])
105
128
106
-
### GET `/schools`
129
+
### `GET /api/v1/users`
107
130
108
-
Output
131
+
Lists users with basic fields; future versions may introduce pagination tokens and filters consistent with AIP-158/160. ([aip.dev][9], [Google AIP][10])
Returns public submissions for a given user, newest first. Authorization rules may further restrict fields in non-public scenarios. ([Google Cloud][8])
136
+
137
+
---
138
+
139
+
## Schools
113
140
114
-
Purpose: List all schools.
141
+
### `GET /api/v1/schools`
115
142
116
-
### GET `/schools/{id}`
143
+
Returns an array of schools (id/slug/name/updated\_at). List endpoints are designed to adopt cursor pagination in a future revision (AIP-158). ([aip.dev][9])
117
144
118
-
Purpose: Get a school by id.
145
+
### `GET /api/v1/schools/{school}`
146
+
147
+
Retrieves a school by **slug**; `404` if not found. Slug-based resource naming supports human-readable discovery while remaining URL-safe. ([aip.dev][1])
119
148
120
149
---
121
150
122
151
## Courses
123
152
124
-
### GET `/courses`
153
+
### `GET /api/v1/schools/{school}/courses`
125
154
126
-
Purpose: List courses. Optional filter by `schoolId`.
155
+
Lists courses under a school (by school **slug**). Future revisions may add pagination and filtering (AIP-158/160). ([aip.dev][9], [Google AIP][10])
Retrieves a problem by three slugs. The response contains metadata (name/description), language limits, code/time/memory limits, and an optional structured `artifact` (JSON). ([Cloudflare Docs][11])
139
172
140
-
### GET `/courses/{courseId}/problems/{id}`
173
+
### `GET /api/v1/problems/{id}`
141
174
142
-
Purpose: Get problem detail.
175
+
Retrieves a problem by **id** (stable identifier). ID-based paths support “stable addressing” from logs, queues, or emails without requiring the hierarchical context. This dual model—slug for discovery, id for stability—follows common AIP guidance on resource names. ([aip.dev][1])
143
176
144
177
---
145
178
146
179
## Submissions
147
180
148
-
### POST `/problems/{id}/submissions`
181
+
### `POST /api/v1/problems/{id}/submissions`
149
182
150
-
Input
183
+
Creates a submission for a problem id; body:
151
184
152
185
```json
153
-
{ "code": "..." }
186
+
{ "code": "…", "language": "cpp23" }
154
187
```
155
188
156
-
Output (201)
189
+
Response (`201 Created`)
157
190
158
191
```json
159
192
{
160
193
"ok": true,
161
194
"data": {
162
-
"submissionId": "s_...",
163
-
"userId": "u_...",
164
-
"problemId": "...",
165
-
"status": "queued",
195
+
"submissionId": "s_…",
196
+
"userId": "u_…",
197
+
"problemId": "…",
198
+
"status": "IQ",
166
199
"createdAt": 1736272000
167
200
}
168
201
}
169
202
```
170
203
171
-
Purpose: Create a submission (enqueued for judging).
204
+
The server enqueues an asynchronous judge task and returns `201` with the resource representation; failures return a problem document. ([rfc-editor.org][5])
205
+
206
+
### `GET /api/v1/submissions/{id}`
207
+
208
+
Retrieves a submission by id (public fields). If private data exists, apply authorization (owner-only `403`). `404` if not found. ([rfc-editor.org][5])
172
209
173
-
### GET `/submissions/{id}`
210
+
### `GET /api/v1/problems/{id}/submissions`
174
211
175
-
Purpose: Get submission detail (must be owner).
212
+
Lists public submissions for a given problem (newest first). ([Google Cloud][8])
213
+
214
+
### `GET /api/v1/users/{slug}/submissions`
215
+
216
+
Lists public submissions for a given user (newest first). ([Google Cloud][8])
217
+
218
+
> Notes on lists: while the current API supports a simple `limit`, future versions are expected to adopt **AIP-158** token-based pagination and optional **AIP-160** filters. ([aip.dev][9], [Google AIP][10])
219
+
220
+
---
176
221
177
-
### GET `/users/me/submissions`
222
+
#Error Model
178
223
179
-
Purpose: List the current user’s submissions (newest first).
224
+
* All errors use **RFC 9457** (`type`, `title`, `status`, `detail`, `instance`), with optional custom members. Use `Content-Type: application/problem+json`. When `Accept` excludes JSON, respond `406` with a problem document to explain negotiation failure. ([datatracker.ietf.org][2])
225
+
* JSON family is recognized via the `+json` structured syntax suffix, so `application/problem+json` participates in negotiation correctly. ([datatracker.ietf.org][4])
0 commit comments