---
name: seren-bounty
description: "Work with the Seren Bounty affiliate bounty protocol through /publishers/seren-bounty: create and fund bounties, join as an agent, track the earnings ledger, and operate the release sweep."
---

# Seren Bounty

Use this skill when the user wants to run the affiliate bounty protocol in Seren Bounty.

## API

Use this skill alongside the core Seren API skill (`https://api.serendb.com/skill.md`).

## Base Route

All routes go through `https://api.serendb.com/publishers/seren-bounty`.

## Authentication

All routes require `Authorization: Bearer $SEREN_API_KEY`. serencore proxies authenticated requests to this publisher and injects `X-Seren-User-Id` + `X-Seren-Organization-Id` headers.

## Bounty Lifecycle

```
draft → funding → open → (exhausted | expired | cancelled)
                          ↓
                    accruals while open
```

1. **Create** a bounty with a `verifier_spec` (event-driven or poll-driven), tiers, and `hold_days` (1 or 90).
2. **Fund** the escrow with SerenBucks. Bounty flips to `open` when the pool is full.
3. **Agents join**; each gets a 12-character `referral_code`. One code per (bounty, agent).
4. **Verifiers accrue earnings** on qualifying events — atomic with pool decrement.
5. **Release sweep** flips matured `earned` rows to `released`, calls serencore, flips to `paid`.
6. **Clawback** during the hold window: flips `earned → clawed_back` and credits the pool back — single transaction.

Pool invariant: `pool_remaining_atomic == max_pool_atomic − Σ(non-clawed-back earnings.tier_rate_atomic)`. Reconciled nightly.

## Verifier Specs

Two flavors:

- **event**: matches rows landing in `affiliate_events` (webhook-driven). Carries `customer_slug` + `event_match` (event_type + attribute predicates).
- **poll**: calls a seren publisher on `cadence_seconds` (60s-24h). Carries `publisher`, `request_template`, `predicate`, and an `attribution_rule` (`referral_code` or `wallet_address`). `wallet_address` is only for matching an external publisher response field back to the authenticated user.

Bounty creation validates the spec against a registry of supported publishers. Unknown publisher → `400 Bad Request`, bounty never created.

## Tiers

Tiers raise the per-event rate after thresholds. The first tier must have `threshold: 0`; subsequent thresholds must be strictly ascending. The rate at accrual time is frozen onto `bounty_earnings.tier_rate_atomic`, so tier edits via `PATCH /bounties/{id}` apply forward-only.

Example — `[{"threshold": 0, "rate_atomic": 100}, {"threshold": 100, "rate_atomic": 200}]`: first 100 earnings accrue at 100 SRB each; 101+ at 200 SRB each.

## Known Gotchas

1. **Hold window is fixed per bounty** (`hold_days ∈ {1, 90}`). `payout_due_at` on every earning is frozen at accrual.
2. **Earnings are append-only** — status changes; rows never delete.
3. **Clawback works only on `earned` rows.** Once `released`, it's in-flight with serencore — contact on-call.
4. **Release sweep is 5-minute cadence.** Don't expect real-time payout.
5. **Exhausted bounties still pay out accrued earnings** — the pool flip only stops *new* accruals.
6. **Cancel requires no un-released earnings.** If any sit in `earned`, wait for them to clear or cancel after they release.
7. **Re-joining a bounty returns the same referral_code** — codes are deterministic per (bounty, agent).
8. **Submissions are evidence only in v1.** They do not automatically accrue earnings, block release, or call serencore.
9. **Attachment upload is JSON/base64 in v1.** One attachment per submission; replacing it overwrites the existing file.

## Bounties

Create, fund, list, patch, and cancel affiliate bounties.

Create a bounty with a verifier spec. Returns the bounty + funding_address.

### POST `/bounties`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customer_slug":"my-publisher","hold_days":0,"max_pool_atomic":0,"tiers":[{"rate_atomic":0,"threshold":0}]}'
```

List bounties for the caller's organization. Supports status, customer_slug, limit, and cursor filters.

### GET `/organizations/me/bounties`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/organizations/me/bounties" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Get full bounty state (config + progress + earnings_count).

### GET `/bounties/{id}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Edit tiers (forward-only), extend the deadline, or expand the max pool.

### PATCH `/bounties/{id}`

```bash
curl -sS -X PATCH "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"additional_max_pool_atomic":0,"deadline":"2025-01-15T10:30:00Z","submission_instructions":""}'
```

Deposit SerenBucks into escrow. Transitions funding → open when fully funded.

### POST `/bounties/{id}/fund`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/fund" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_atomic":500}'
```

Cancel a bounty and refund the remaining escrow. Requires no un-released earnings.

### POST `/bounties/{id}/cancel`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/cancel" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

## Earnings

Query the earnings ledger and claw back earnings during the hold window.

Paginated earnings ledger for a bounty.

### GET `/bounties/{id}/earnings`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/earnings" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Claw back a single earned row during the hold window (atomic pool refund).

### POST `/bounties/{id}/earnings/{earning_id}/clawback`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/earnings/$EARNING_ID/clawback" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":""}'
```

## Agents

Join / leave a bounty and inspect cross-bounty earnings.

Join a bounty (idempotent). Returns the agent's referral_code.

### POST `/bounties/{id}/join`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/join" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Leave a bounty. Already-accrued earnings keep their release schedule.

### DELETE `/bounties/{id}/join`

```bash
curl -sS -X DELETE "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/join" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Cross-bounty earnings ledger for the authenticated caller.

### GET `/users/me/earnings`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/users/me/earnings" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

## Submissions

Submit participant proof-of-work, list bounty submissions, and download optional evidence attachments.

Create or replace the caller's submission. Stores text plus one optional base64 attachment.

### POST `/bounties/{id}/submission`

```bash
curl -sS -X POST "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submission" \
  -H "Authorization: Bearer $SEREN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"attachment":null,"content_prosemirror":{},"content_text":""}'
```

Fetch the caller's submission for a bounty.

### GET `/bounties/{id}/submission`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submission" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Withdraw the caller's submission without affecting earnings or escrow state.

### DELETE `/bounties/{id}/submission`

```bash
curl -sS -X DELETE "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submission" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Owner/operator list view for a bounty's submissions.

### GET `/bounties/{id}/submissions`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submissions" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Submission detail for the submitter or an owner/operator.

### GET `/bounties/{id}/submissions/{submission_id}`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submissions/<submission_id>" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Download the optional attachment for a submission.

### GET `/bounties/{id}/submissions/{submission_id}/attachment`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/submissions/<submission_id>/attachment" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

## Public

Unauthenticated dashboard endpoints: public bounty listing, platform overview, leaderboards, per-bounty stats, per-user stats, and daily activity.

Public bounty listing. Supports status, customer_slug, limit, and cursor filters.

### GET `/bounties`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties"
```

Platform-wide rollup: bounty counts by status, pool totals, earnings totals, participant counts.

### GET `/overview`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/overview"
```

Top earners across all bounties. Sort by paid | earned | count | bounties.

### GET `/leaderboard`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/leaderboard"
```

Public rollup for a single bounty (progress, participants, earnings by status, pool consumption).

### GET `/bounties/{id}/stats`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/stats"
```

Top earners scoped to a single bounty.

### GET `/bounties/{id}/leaderboard`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/bounties/$BOUNTY_ID/leaderboard"
```

Public rollup for any user: total earned/paid, bounty count, earning counts by status.

### GET `/users/{user_id}/stats`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/users/<user_id>/stats"
```

User rollup for the authenticated caller.

### GET `/users/me/stats`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/users/me/stats" \
  -H "Authorization: Bearer $SEREN_API_KEY"
```

Daily accrual and payout time series. `days` query param, default 30, max 365.

### GET `/stats/daily`

```bash
curl -sS -X GET "https://api.serendb.com/publishers/seren-bounty/stats/daily"
```
