Skip to main content

Missions

Three endpoints. All require Authorization: Bearer <JWT>.

GET /v1/missions

List missions with the caller's progress folded in.

curl https://api.questkit.jairukchan.com/v1/missions?status=active&limit=10 \
-H "Authorization: Bearer <JWT>"
Query paramTypeDescription
campaignIdstringFilter to a single campaign.
statusstringactive / completed / claimed / locked / all (default).
limitnumberPage size.
cursorstringOpaque cursor from a previous response's nextCursor.

Response — 200 OK

{
"missions": [
{
"id": "daily-streak",
"title": "Daily Streak",
"description": "Log in 7 days in a row.",
"criteria": {
"eventName": "daily.login",
"count": 7,
"window": "lifetime"
},
"reward": { "kind": "currency", "currency": "gold", "amount": 100 },
"campaignId": null,
"expiresAt": null,
"iconUrl": null
}
],
"progress": {
"daily-streak": {
"userId": "usr_demo_123",
"missionId": "daily-streak",
"status": "active",
"progress": 0.42,
"currentCount": 3,
"targetCount": 7,
"updatedAt": 1716100000000
}
},
"nextCursor": "eyJpZCI6Im..."
}

progress is keyed by mission id; entries only exist for missions that have a server-side progress row for the caller.


GET /v1/missions/:id

Fetch one mission and the caller's progress.

curl https://api.questkit.jairukchan.com/v1/missions/daily-streak \
-H "Authorization: Bearer <JWT>"

Response — 200 OK

{
"mission": {
"id": "daily-streak",
"title": "Daily Streak",
"description": "Log in 7 days in a row.",
"criteria": {
"eventName": "daily.login",
"count": 7,
"window": "lifetime"
},
"reward": { "kind": "currency", "currency": "gold", "amount": 100 }
},
"progress": {
"userId": "usr_demo_123",
"missionId": "daily-streak",
"status": "active",
"progress": 0.42,
"currentCount": 3,
"targetCount": 7,
"updatedAt": 1716100000000
}
}

progress is null if the user has never fired a qualifying event for this mission.

Errors

HTTPerror codeMeaning
404mission_not_foundNo mission with this id.

POST /v1/missions/:id/claim

Atomic transition completedclaimed. Mints the reward, increments the balance (currency rewards only), broadcasts reward.granted + balance.changed SDKUpdates.

curl -X POST https://api.questkit.jairukchan.com/v1/missions/daily-streak/claim \
-H "Authorization: Bearer <JWT>" \
-H "Idempotency-Key: abc123-uuid"

Response — 200 OK

{
"progress": {
"userId": "usr_demo_123",
"missionId": "daily-streak",
"status": "claimed",
"progress": 1,
"currentCount": 7,
"targetCount": 7,
"updatedAt": 1716100100000
},
"balance": {
"userId": "usr_demo_123",
"currency": "gold",
"amount": 1100,
"updatedAt": 1716100100000
},
"reward": { "kind": "currency", "currency": "gold", "amount": 100 }
}

balance is null if the reward kind is not currency.

Errors

HTTPerror codeMeaning
404mission_not_foundThe mission doesn't exist at all.
409claim_not_readyEither no progress row, or the row's status isn't completed. Try again later.

Idempotency

Pass Idempotency-Key. The response is cached under (userId, "claim:<key>") for 24h; replays return the original payload with X-Idempotent-Replay: hit. SSE broadcasts only fire on the first (non-replayed) claim — replays do not re-broadcast.