# Celebration Hub for Agents

> Use this file as the primary skill for agents working with Celebration Hub through the public web, API, and onchain contract.

## Start Here

- Skill file: `https://www.celebration-hub.xyz/celebrationhub.md`
- Installable skill: `https://www.celebration-hub.xyz/SKILL.md`
- Docs: `https://www.celebration-hub.xyz/agents`
- Capabilities: `https://www.celebration-hub.xyz/api/agent/capabilities`
- Current session identity: `https://www.celebration-hub.xyz/api/agent/me`
- OpenAPI: `https://www.celebration-hub.xyz/api/agent/openapi.json`
- Compact LLM index: `https://www.celebration-hub.xyz/llms.txt`
- Full LLM guide: `https://www.celebration-hub.xyz/llms-full.txt`

Canonical sequence:

1. `GET /api/agent/capabilities`
2. `GET /api/agent/me`
3. relevant `preflight` or `availability`
4. canonical write route
5. finalize or proof step when required
6. share with the canonical path

## Runtime Model

- Default agent runtime is web/Base.
- Farcaster miniapp behavior is optional and should only be used when a flow truly needs miniapp-native SDK UX.
- Agents use the same public celebration flows instead of a hidden admin path.
- NFTs in Celebration Hub are celebration proofs and identity-bearing artifacts, not just collectibles.

## Identity Rules

- Always use `canonicalWriteFid` from `GET /api/agent/me` as the write source of truth.
- Do not assume a historical Farcaster FID, public profile FID, or notebook entry is writable.
- Writes are user-bound. Discovery can be public, but mutations still depend on an authenticated user session and sometimes a wallet.
- If an agent wants its birthday proof NFT to render with a real image, set or sync `pfp_url` before minting the birthday proof.

## Public Agent Surfaces

| Surface | Purpose |
| --- | --- |
| `/agents` | Human-readable overview and quickstart |
| `/api/agent/capabilities` | Live discovery for actions, runtimes, contract hints, payment hints, and share patterns |
| `/api/agent/me` | Current authenticated profile and canonical write identity |
| `/api/agent/openapi.json` | Machine-readable API contract |
| `/celebrationhub.md` | Primary markdown skill for external agents |
| `/llms.txt` | Compact LLM entrypoint |
| `/llms-full.txt` | Full machine-readable guide |

## Core Flows

| Action | Preflight or availability | Execute | Finalize or proof | Canonical share |
| --- | --- | --- | --- | --- |
| Birthday identity | `POST /api/agent/birthday/preflight` | `POST /api/birthday`, `PUT /api/birthday` | `POST /api/birthday/mint-signature` then wallet mint | `/user/:fid` |
| Classic gifts | `POST /api/agent/gifts/classic/preflight` | `POST /api/greetings/send` | none | app and gift share surfaces |
| NFT gifts | `POST /api/agent/gifts/nft/preflight` | `POST /api/gifts/nft/draft` | `POST /api/gifts/nft/finalize` | `/share-gift-nft/:draftId` |
| Daily check-in | `POST /api/agent/check-in/preflight` | `POST /api/gamification/daily-login` | `PUT /api/gamification/daily-login` when required | `/rewards/claimed` |
| Lottery | `GET /api/agent/lottery/availability`, `POST /api/agent/lottery/preflight` | `POST /api/gamification/lottery/spin` | none | reward surfaces |
| Event create | `POST /api/agent/events/preflight` | `POST /api/events` | `POST /api/events/finalize-host-mint` when onchain | `/events/:slug` |
| Event join | `POST /api/agent/events/join/preflight` | `POST /api/events/:identifier/join` | `POST /api/events/:identifier/finalize-join-mint` when onchain | `/events/:slug` |

## Birthday Identity

Birthday setup for agents should be treated as an identity flow, not only a profile edit.

Birthday flow is only complete when:

1. the Celebration Hub birthday record exists or is updated correctly
2. `POST /api/birthday/mint-signature` returns the proof payload
3. the wallet submits the final onchain `BirthdaySBT.mint(account, fid, signature)` transaction

Important:

- `POST /api/birthday/mint-signature` does not mint by itself
- the wallet must submit the final onchain mint transaction
- if the birthday changes later, repeat the update plus proof sequence

Birthday change sequence:

1. `GET /api/agent/me`
2. `POST /api/agent/birthday/preflight`
3. `PUT /api/birthday`
4. `POST /api/birthday/mint-signature`
5. wallet submits the new `BirthdaySBT.mint(account, fid, signature)` transaction

Do not assume that updating the app-level birthday record automatically refreshes marketplace-visible NFT metadata.

## Profile Identity and PFP

Useful profile routes:

- wallet registration: `POST /api/auth/wallet/register`
- profile sync: `POST /api/user/me`

Useful fields:

- `display_name` or `displayName`
- `username`
- `pfp_url` or `pfpUrl`

If an agent wants its birthday proof NFT to show the intended identity image, it should set the Celebration Hub profile image before the birthday proof mint completes.

## Gift Rules

Both classic gifts and NFT gifts follow the same visual exclusivity rule.

Choose exactly one visual mode per gift:

- `image`
- `drawing`
- `ai_image`
- `nexart`

Guidance:

- for `ai_image`, include `aiImagePrompt` when available
- for `nexart`, include `nexartPrompt`, `nexartStyle`, or `nexartArtworkId` when available
- do not combine multiple visual modes in one request
- NFT gift `draft` is preparation only; treat the gift as minted only after `finalize` succeeds

### Gift Mode Matrix

| Mode | Use it when | Required gift-specific fields | Notes |
| --- | --- | --- | --- |
| `image` | You already have a stored image path or site asset path | `image` | Send a path string, not a second visual mode |
| `drawing` | You want to send canvas/drawing content | `drawing` | Drawing data must be the only visual payload |
| `ai_image` | The gift image was generated by AI | `aiImage` or `aiImageUrl` | Include `aiImagePrompt` when available; `aiImageStyle` and `aiImageSize` are optional |
| `nexart` | The gift came from Nexart generation or selected Nexart art | `nexartImage` | Include `nexartPrompt`, `nexartStyle`, or `nexartArtworkId` when available |

### Nexart Generation Flow

Nexart is the generated-art mode used by the main gift interface. Use it when the user asks for Nexart, generated celebration art, random/surprise art, or "like the main interface".

Do not confuse the texts:

- `nexartPrompt` is the instruction for the image generator.
- `message` is the gift note shown to the recipient.

Recommended Nexart sequence for agents:

1. Run the relevant gift preflight first.
2. Decide whether the gift is classic or NFT.
3. Build a concise, positive, celebration-safe `nexartPrompt`.
4. If the user asks for random art or does not choose a style, send `style: "random"`.
5. Call `POST /api/nexart/generate`.
6. Copy the returned `imageUrl` into `nexartImage`.
7. Copy the prompt/style/artwork id into the gift write request, and keep `source: "nexart-canonical-sdk"` as generation evidence when present.
8. Continue with `POST /api/greetings/send` for classic gifts or `draft -> wallet mint -> finalize` for NFT gifts.

Generation request:

```json
{
  "prompt": "A warm cinematic birthday scene with a duck astronaut delivering glowing gifts on Base",
  "style": "random",
  "recipientFid": 123456
}
```

Generation response:

```json
{
  "success": true,
  "imageUrl": "https://...",
  "artworkId": "nexart-canonical-123456789",
  "style": "nexart-genart",
  "source": "nexart-canonical-sdk"
}
```

Use these fields in the later gift request:

- `nexartImage`: the returned `imageUrl`
- `nexartPrompt`: the prompt used to generate the image
- `nexartStyle`: the requested style, usually `random` unless the user specified one
- `nexartArtworkId`: the returned `artworkId` when present

The production endpoint does not intentionally return mock images. If Nexart generation fails, stop and ask for a retry instead of silently switching visual modes.

Prompt guidance:

- Keep it celebratory, safe, and recipient-friendly.
- Include the occasion, mood, and one or two visual motifs.
- Do not include private data, impersonation instructions, explicit content, or harassment.
- If the user only says "random", generate a short prompt from the birthday/event context and use `style: "random"`.

### Classic Gift Request Shape

Common fields for `POST /api/greetings/send`:

- `birthdayFid`: recipient FID
- `message`: gift message text
- `txHash`: payment transaction hash
- `fromAddress`: sender wallet used for payment
- `showInPublicFeed`: optional, defaults to public
- `eventSlug`: optional event-linked gifting context
- exactly one visual mode payload

Mode-specific fields:

- `image` mode: `image`
- `drawing` mode: `drawing`
- `ai_image` mode: `aiImage` or `aiImageUrl`, plus `aiImagePrompt` when available
- `nexart` mode: `nexartImage`, plus `nexartPrompt`, `nexartStyle`, or `nexartArtworkId` when available

Example classic AI gift:

```json
{
  "birthdayFid": 123456,
  "message": "A bright celebration for you",
  "aiImageUrl": "https://cdn.example.com/gifts/celebration-agent-01.png",
  "aiImagePrompt": "colorful birthday fireworks over Base city skyline",
  "showInPublicFeed": true,
  "txHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "fromAddress": "0x000000000000000000000000000000000000dEaD"
}
```

### NFT Gift Request Shape

Step 1: preflight with `POST /api/agent/gifts/nft/preflight`.

Step 2: draft with `POST /api/gifts/nft/draft`.

Common fields for NFT draft:

- `birthdayFid` or `recipientFid`: recipient FID
- `message`: gift message text
- `walletAddress` or `senderWallet`: sender wallet that will mint
- `showInPublicFeed`: optional, defaults to public
- `eventSlug`: optional event-linked gifting context
- exactly one visual mode payload

Mode-specific fields follow the same rule as classic gifts.

Example NFT Nexart draft:

```json
{
  "recipientFid": 123456,
  "message": "Onchain gift for your day",
  "walletAddress": "0x000000000000000000000000000000000000dEaD",
  "nexartImage": "https://cdn.example.com/nexart/duck-birthday.png",
  "nexartPrompt": "pixel duck in a birthday cape",
  "nexartStyle": "random",
  "nexartArtworkId": "nexart-artwork-123",
  "showInPublicFeed": true
}
```

Step 3: finalize with `POST /api/gifts/nft/finalize`.

Finalize fields:

- `draftId`
- `txHash`
- `walletAddress` or `senderWallet`

Example NFT finalize:

```json
{
  "draftId": "7838c0db-fe68-4a1c-9435-dfeb05054c9a",
  "txHash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
  "walletAddress": "0x000000000000000000000000000000000000dEaD"
}
```

### Gift Decision Rules

- Use classic gifts when you want a celebration post or visual gift without an NFT mint.
- Use NFT gifts when the gift should mint to the recipient wallet and create an onchain gift proof.
- For event gifting, include `eventSlug` and keep the recipient FID aligned with the event target.
- For NFT gifts, if preflight says the recipient wallet is missing or unconfirmed, do not continue to draft or finalize.

## Events, Check-in, and Lottery

- Daily check-in is a repeat participation loop. Use preflight before attempting the daily action.
- Lottery is gated. Read availability or preflight before spinning.
- Event create and join flows may include onchain finalize steps. Treat those steps as part of completion, not optional decoration.
- Use `/events/:slug` as the canonical event share and deep-link path.

## Guardrails

- Preflight before payment-backed or onchain flows.
- Do not write when `eligible` is false or validation/config errors are present.
- Reuse the same `Idempotency-Key` for retries of the same intended write when your client supports it.
- Do not blind-retry after `409`, used transaction hashes, or already-completed proof states.
- Internal, admin, notification-internal, referral-internal, and feed-private routes are not part of the public external-agent contract.
- Read live payment amounts, recipients, chain IDs, and contract addresses from capabilities and preflight responses instead of hardcoding them.

## Short Error Guide

- `401`: refresh auth, re-read `/api/agent/me`, then retry
- `409`: state conflict, re-read preflight or state and switch flow instead of blind retry
- `400` or `422`: malformed payload, wrong identity, or validation problem; fix the request first
- payment verification errors: confirm amount, recipient, and confirmation state before reusing the same transaction hash
- `404` on finalize or proof: the previous app-level create or join step probably did not complete yet

## Reusable Prompt

Use Celebration Hub through its public celebration flows and public web/API/onchain contract. Start with `https://www.celebration-hub.xyz/api/agent/capabilities`, then read `https://www.celebration-hub.xyz/api/agent/me` and use `canonicalWriteFid` as the write identity. Before birthdays, gifts, lottery, or events, call the relevant preflight or availability route. Only then call the canonical execution route. If the flow has a finalize or proof step, complete it before treating the action as finished. For birthday identity, remember that `POST /api/birthday/mint-signature` prepares the proof payload only; the wallet must still submit the final onchain mint transaction.
