Starholder API
API Reference

Marketplace — Bounties

Create, claim, submit, review, and finalize bounties in the Starholder marketplace.

The bounty marketplace connects content demand with creator supply. There are two bounty types:

  • text_story — You need someone to write a narrative. You post the brief, set a budget, and a creator writes a story that you will own once accepted.
  • media_production — You already have a story but need images produced for it. You post the work manifest items (entity portraits, scene illustrations, setting art) and a creator produces the media.

Every bounty carries a $STAR budget. When you create a bounty, your $STAR is placed in escrow — locked so the fulfiller knows the funds exist and will be released to them upon acceptance. If the bounty is cancelled or expires, the escrowed $STAR is returned to you.

Bounty Lifecycle

create → claim → submit → review → finalize
                                  ↘ revision_requested → resubmit

When a creator claims a bounty, they commit to delivering by a deadline. If they claim but don't deliver before the expiration time, the claim expires automatically and the bounty reopens for someone else to take.

Self-fulfillment (issuer settles their own bounty) uses the atomic /settle endpoint.


GET /world/{worldId}/bounties

List bounties with optional filters.

Auth: Bearer or session | Capability: canAccessBounties

curl https://www.starholder.xyz/api/v1/world/starholder_main/bounties \
  -H "Authorization: Bearer $API_KEY"

Returns paginated bounty list with bounties, total, cursor.


POST /world/{worldId}/bounties

Create a new bounty. The specified budget is immediately escrowed from your $STAR balance.

Auth: Bearer or session | Capability: canAccessBounties | Scope: bounty:post

{
  "type": "text_story",
  "title": "The Lost Archives of the Triangle",
  "objective": "Write a 2000-word story about...",
  "creativeBrief": "Focus on atmospheric tension...",
  "budget": 100,
  "sourceGapId": "gap_abc123"
}

GET /world/{worldId}/bounties/{bountyId}

Retrieve a single bounty with full detail, including current lifecycle status, claim information, and linked gap/seed data.


POST /world/{worldId}/bounties/{bountyId}/claim

Claim an open bounty. This reserves the bounty for you until the expiration time.

Auth: Bearer or session | Scope: bounty:claim

{ "expiresAt": "2026-05-01T00:00:00Z" }

POST /world/{worldId}/bounties/{bountyId}/submit

Submit fulfillment work for a claimed bounty.

Auth: Bearer or session | Scope: bounty:submit

Text submissions include narrative content. Media submissions reference staged assets uploaded via the staging endpoint.


POST /world/{worldId}/bounties/{bountyId}/review

Review a bounty submission (issuer only).

Auth: Bearer or session | Scope: bounty:review

{
  "claimId": "claim_001",
  "submissionId": "bsub_001",
  "decision": "accept",
  "feedback": "Excellent work."
}

Decisions: accept, reject, revision_requested. Accepting may auto-finalize and release escrow to the fulfiller.


POST /world/{worldId}/bounties/{bountyId}/finalize

Finalize an accepted bounty. Releases escrowed $STAR to the fulfiller and triggers any media top-up hooks.

Auth: Bearer or session | Scope: bounty:review


POST /world/{worldId}/bounties/{bountyId}/settle

Atomic self-fulfillment path (issuer only, text_story bounties). Combines submit + auto-accept + finalize + escrow release in one call. Use this when you posted a bounty and ended up writing the story yourself.

Auth: Session | Scope: bounty:submit


GET /world/{worldId}/bounties/{bountyId}/notes

List notes on a bounty thread. Notes are the discussion channel between issuer and fulfiller.

POST /world/{worldId}/bounties/{bountyId}/notes

Post a note to the bounty discussion thread.

Auth: Bearer or session | Scope: bounty:note


GET /world/{worldId}/bounties/{bountyId}/work-manifest

Retrieve the work manifest associated with a bounty (for media_production bounties, this lists the specific assets to produce).


GET /world/{worldId}/bounties/{bountyId}/submission/{submissionId}

Retrieve a specific bounty submission with optional presigned asset URLs for any uploaded media.


POST /world/{worldId}/bounties/{bountyId}/staging/upload-url

Get a presigned S3 upload URL for staging media assets before submitting them against a bounty.

{
  "uploadUrl": "https://s3...",
  "assetKey": "...",
  "stagingSessionId": "...",
  "expiresAt": "..."
}

GET /world/{worldId}/bounties/media-sources

List eligible media sources for media production bounties.