# Achievements for PlayDrop games

Declare standard and incremental achievements with icons in catalogue.json, unlock them and report progress with sdk.achievements.

Source: https://www.playdrop.ai/create/learn/achievements

Achievements mark goals in your game, with an icon and a description players see on PlayDrop. They work for guests and signed-in players.

## Declare achievements

```json
{
  "achievements": [
    { "key": "first-win", "displayName": "First flag", "description": "Reach the flag once",
      "kind": "STANDARD", "icon": "achievements/first-win.png" },
    { "key": "collector", "displayName": "Collector", "description": "Collect 100 stars",
      "kind": "INCREMENTAL", "maxProgress": 100, "icon": "achievements/collector.png" },
    { "key": "secret-room", "displayName": "Secret room", "description": "Find the hidden room",
      "kind": "STANDARD", "hidden": true, "icon": "achievements/secret-room.png" }
  ]
}
```

- `key` follows the same format as [leaderboard](https://www.playdrop.ai/create/learn/leaderboards) keys.
- `kind` is `STANDARD` (unlocked once) or `INCREMENTAL` (unlocked when progress reaches `maxProgress`, a positive integer).
- `icon` is a PNG in the package. Use a clear square image that reads at small sizes.
- `hidden: true` keeps the name and description secret until unlocked.

Published keys cannot be removed, and `kind`, `maxProgress` and `hidden` cannot change. Retire an achievement with `"status": "RETIRED"`.

## Unlock and report progress

```js
await sdk.achievements.unlock("first-win");
await sdk.achievements.setProgressAtLeast("collector", starsCollected);

const { achievements } = await sdk.achievements.list();
const { achievement } = await sdk.achievements.get("collector");
```

- `setProgressAtLeast` takes the total so far, never a delta. Progress only rises, is capped at `maxProgress` and unlocks there.
- Both calls return `{ accepted, changed, unlocked, progress, unlockedAt, achievement }`; `changed` is false when nothing new happened, so you can show your own toast only once.
- `list({ includeHiddenDefinitions: true, includeRetired: true })` includes hidden and retired definitions.

Unlock only during real play, never in previews or captures. Without any player session the calls resolve without being stored.

## Good achievements

Mix early ones that teach the game with long-term goals. Name the action, not the reward: "Win without taking damage" says what to do. A dozen thoughtful achievements beat a hundred trivial ones.

## Related guides

- [Leaderboards](https://www.playdrop.ai/create/learn/leaderboards): Declare leaderboards in catalogue.json, submit scores with sdk.leaderboards and show top ranks and the player's neighbors. Score types, limits and update rules.
- [Cloud saves](https://www.playdrop.ai/create/learn/cloud-saves): Save and load player progress with sdk.me.appData and updateAppData, for guests and signed-in players, with the rules for writes, previews and offline play.
- [catalogue.json](https://www.playdrop.ai/create/learn/catalogue-json): The catalogue.json fields PlayDrop games use: identity, listing, play modes, surfaces, sign-in, Instant, preloading, media, translations, scores and servers.
