Skip to main content
All endpoints are prefixed with /api/completions. Responses use Content-Type: application/json. Endpoints that modify data require an Authorization: Bearer <accessToken> header.

POST /api/completions

Submit a completion for a challenge. The server verifies that the provided GPS coordinates are within an allowed distance of the challenge location before recording the completion. Aura points and streak are updated automatically inside a database transaction.
Auth required: Yes — include Authorization: Bearer <accessToken>. This endpoint is rate-limited. Each challenge can only be completed once per user; a duplicate submission returns 400.

Request body

challengeId
integer
required
ID of the challenge being completed.
latitude
number
required
User’s current latitude (-90 to 90).
longitude
number
required
User’s current longitude (-180 to 180).
imageUrl
string
required
URL of the proof photo for this completion. Must be a valid URL.
caption
string
Optional caption for the completion post. Maximum 500 characters.

Response — 201 Created

success
boolean
true on success.
message
string
"Challenge completed successfully!"
data
object

Error responses

StatusCondition
400Invalid challengeId, missing imageUrl, GPS coordinates outside the allowed distance from the challenge location, or challenge already completed by this user
401Missing or invalid Bearer token
404Challenge not found
429Rate limit exceeded

Example

curl -X POST http://localhost:3000/api/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <accessToken>" \
  -d '{
    "challengeId": 42,
    "latitude": 35.3005,
    "longitude": -120.6596,
    "imageUrl": "https://<project>.supabase.co/storage/v1/object/public/completion-images/42/photo.jpg",
    "caption": "Made it to the top!"
  }'

GET /api/completions

Return a paginated list of completions. Supports filtering by user, challenge, and date range. Each completion includes embedded user and challenge objects.

Query parameters

userId
integer
Filter completions by user ID.
challengeId
integer
Filter completions by challenge ID.
startDate
string
ISO 8601 date-time. Return only completions at or after this timestamp. Must be before or equal to endDate if both are supplied.
endDate
string
ISO 8601 date-time. Return only completions at or before this timestamp.
page
integer
Page number. Defaults to 1.
limit
integer
Items per page. Defaults to 20, range 1100.
sortOrder
string
Sort order for completedAt. One of asc or desc. Defaults to desc.

Response — 200 OK

success
boolean
true on success.
data
array
pagination
object

Error responses

StatusCondition
400Invalid query parameters (e.g. non-numeric ID, startDate after endDate, limit out of range)

Example

curl "http://localhost:3000/api/completions?userId=7&limit=5&sortOrder=desc"

GET /api/completions/:id

Return a single completion by its ID with full user and challenge details.

Path parameters

id
integer
required
The numeric ID of the completion.

Response — 200 OK

success
boolean
true on success.
data
object

Error responses

StatusCondition
400id is not a valid integer
404Completion not found

Example

curl "http://localhost:3000/api/completions/101"

PATCH /api/completions/:id

Update the caption of an existing completion. Only the owner of the completion may edit it.
Auth required: Yes — include Authorization: Bearer <accessToken>. The authenticated user must own the completion.

Path parameters

id
integer
required
The numeric ID of the completion to update.

Request body

caption
string
Updated caption text. Maximum 500 characters. Pass null or omit to clear the caption.

Response — 200 OK

success
boolean
true on success.
data
object
The updated completion, including embedded user (id, name) and challenge (id, title, pointsReward) objects.

Error responses

StatusCondition
400id is not a valid integer, or caption exceeds 500 characters
401Missing or invalid Bearer token
403Authenticated user does not own this completion
404Completion not found

Example

curl -X PATCH http://localhost:3000/api/completions/101 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <accessToken>" \
  -d '{"caption": "Updated: caught the sunrise instead!"}'

POST /api/completions/:id/like

Increment the like count for a completion by 1.
Auth required: Yes — include Authorization: Bearer <accessToken>.

Path parameters

id
integer
required
The numeric ID of the completion to like.

Response — 200 OK

success
boolean
true on success.
data
object

Error responses

StatusCondition
400id is not a valid integer
401Missing or invalid Bearer token
404Completion not found

Example

curl -X POST http://localhost:3000/api/completions/101/like \
  -H "Authorization: Bearer <accessToken>"

DELETE /api/completions/:id/like

Decrement the like count for a completion by 1.
Auth required: Yes — include Authorization: Bearer <accessToken>.

Path parameters

id
integer
required
The numeric ID of the completion to unlike.

Response — 200 OK

success
boolean
true on success.
data
object

Error responses

StatusCondition
400id is not a valid integer
401Missing or invalid Bearer token
404Completion not found

Example

curl -X DELETE http://localhost:3000/api/completions/101/like \
  -H "Authorization: Bearer <accessToken>"

Build docs developers (and LLMs) love