@officexapp/vidfarm-devcli 0.21.62 → 0.21.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/dollarplatoon-skill/SKILL.md +163 -1174
- package/.agents/skills/dollarplatoon-skill/SOURCE.md +62 -0
- package/.agents/skills/dollarplatoon-skill/skill/clients.md +234 -0
- package/.agents/skills/dollarplatoon-skill/skill/feeds.md +326 -0
- package/.agents/skills/dollarplatoon-skill/skill/gigs.md +395 -0
- package/.agents/skills/dollarplatoon-skill/skill/gigworkers.md +324 -0
- package/.agents/skills/dollarplatoon-skill/skill/orders.md +573 -0
- package/.agents/skills/dollarplatoon-skill/skill/payouts.md +234 -0
- package/.agents/skills/dollarplatoon-skill/skill/platform.md +174 -0
- package/.agents/skills/dollarplatoon-skill/skill/prices.md +75 -0
- package/.agents/skills/dollarplatoon-skill/skill/pricing-and-tags.md +255 -0
- package/.agents/skills/dollarplatoon-skill/skill/proofs.md +555 -0
- package/.agents/skills/dollarplatoon-skill/skill/queue.md +404 -0
- package/.agents/skills/dollarplatoon-skill/skill/quickstart.md +191 -0
- package/.agents/skills/dollarplatoon-skill/skill/staging.md +178 -0
- package/.agents/skills/dollarplatoon-skill/skill/tasks.md +588 -0
- package/.agents/skills/dollarplatoon-skill/skill/web-pages.md +586 -0
- package/.agents/skills/vidfarm/SKILL.md +3 -3
- package/.agents/skills/vidfarm/references/core-workflows.md +107 -3
- package/SKILL.director.md +109 -5
- package/SKILL.md +3 -1
- package/clipper.md +20 -0
- package/dist/src/cli.js +50 -6
- package/dist/src/devcli/delivery-seal.js +119 -0
- package/dist/src/devcli/marketplace-console.js +1418 -0
- package/dist/src/devcli/marketplace-gigs.js +162 -16
- package/marketplace.md +299 -1
- package/package.json +24 -3
|
@@ -1,1227 +1,216 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dollarplatoon-skill
|
|
3
3
|
description: >
|
|
4
|
-
Peer-to-peer task payroll
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
Peer-to-peer task payroll on Base L2. Clients fund USDC gigs ("vending machines"), invite
|
|
5
|
+
gigworkers by link, push tasks to their mailboxes, review proofs of work, and pay out
|
|
6
|
+
on-chain. Gigworkers join by invite, poll or receive tasks, submit proofs, and get paid in
|
|
7
|
+
USDC. One mode inverts this: an "order machine" is a shop whose owner does the work, funded
|
|
8
|
+
per order by the buyer who places it. Settlement is recorded in an event ledger and nothing is
|
|
9
|
+
scored or rated; there is no dispute resolution and no public marketplace. Use this skill whenever the user mentions
|
|
10
|
+
dollarplatoon.com, Dollar Platoon, a "vending machine" for gig work, micro-gig payroll, paying
|
|
11
|
+
workers in USDC per task, proof review or approval, rollups and payouts, gig invite links,
|
|
12
|
+
worker mailboxes, task queues and polling, feeds of gigs, escrowing or pre-funding a task on
|
|
13
|
+
chain before it is worked, or placing and funding an order against a shop — and also when they
|
|
14
|
+
are building an agent that earns money doing tasks, or an agent that distributes tasks to
|
|
15
|
+
workers, even if they never name the platform.
|
|
16
|
+
Read this index first, then open only the linked file the task needs.
|
|
12
17
|
---
|
|
13
18
|
|
|
14
19
|
# Dollar Platoon
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
Peer-to-peer task payroll on Base L2. Clients fund gigs with USDC, invite gigworkers privately,
|
|
22
|
+
distribute tasks, review proofs, and pay out on-chain. High volume, low ticket, no contracts, no
|
|
23
|
+
dispute resolution.
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
**This file is an index.** It carries only what every task needs. Everything else lives in the
|
|
26
|
+
files mapped below — open the one your task needs and skip the rest.
|
|
19
27
|
|
|
20
|
-
|
|
28
|
+
Links below are absolute URLs, so they work when this file is fetched from the web. **If you
|
|
29
|
+
already have these files on disk**, the same documents sit next to this one at `skill/<name>.md`
|
|
30
|
+
— read them from the filesystem instead of over the network. **If you fetched this file from
|
|
31
|
+
staging**, the same documents sit at `skill/<name>.md` on that host too; the links below point at
|
|
32
|
+
production's identical copy, so read siblings from the host you started on if that matters to you.
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- **Create Gigs** — Post tasks with USDC funding. Set price per proof, review timeouts, and distribution mode.
|
|
29
|
-
- **Review Proofs** — Approve or reject submissions with a single click. Auto-approve after timeout protects gigworkers.
|
|
30
|
-
- **Track Payouts** — Monitor funds, trigger payouts, and view on-chain transaction history.
|
|
31
|
-
|
|
32
|
-
### For Gigworkers
|
|
33
|
-
|
|
34
|
-
Earn USDC doing tasks. Join private gigs via invite links from clients, submit proofs of work, and get paid automatically on Base L2. Build your reputation as you go.
|
|
35
|
-
|
|
36
|
-
- **Join by Invite** — Clients invite you into their private work networks with invite links. Join gigs that match your skills.
|
|
37
|
-
- **Submit Proofs** — Complete tasks, submit evidence, and track your submissions across all your mailboxes.
|
|
38
|
-
- **Build Reputation** — Every approved proof builds your on-chain reputation across Volume, Quality, and Social dimensions.
|
|
34
|
+
- **API base URL:** `https://dollarplatoon.com/api`
|
|
35
|
+
- **Auth:** an `x-api-key` header on every authenticated call. Get a key at
|
|
36
|
+
[dollarplatoon.com/settings](https://dollarplatoon.com/settings).
|
|
37
|
+
- **Staging:** `https://staging.dollarplatoon.com/api` — same code, Base Sepolia, its own
|
|
38
|
+
accounts, and the only stage where order machines exist. **Build here first:**
|
|
39
|
+
[skill/staging.md](https://dollarplatoon.com/skill/staging.md).
|
|
39
40
|
|
|
40
41
|
---
|
|
41
42
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
**Dimensions:**
|
|
78
|
-
|
|
79
|
-
- **Volume** — Total USDC earned (gigworker) or paid out (client). The most basic measure of activity and trust.
|
|
80
|
-
- **Quality** — Approval rate weighted by rejection severity. Fake proofs damage quality 5x more than low-quality work.
|
|
81
|
-
- **Recency** — Decay function penalizing inactivity. Recent participants are more trustworthy than dormant ones.
|
|
82
|
-
- **Social** — Aggregate star rating from counterparty reviews, weighted by dollar amount exchanged in each gig.
|
|
83
|
-
|
|
84
|
-
**Key Features:**
|
|
85
|
-
|
|
86
|
-
- **Wallet-anchored:** Reputation is tied to wallet addresses, not user accounts. Different wallets per gig means independent reputation histories.
|
|
87
|
-
- **Permissionless:** Anyone can create a wallet and participate. Reputation must be earned.
|
|
88
|
-
- **Gig gating:** Clients can set minimum reputation thresholds (min volume, min quality, min recency) to exclude low-reputation wallets.
|
|
89
|
-
- **Informational only:** Reputation indicators are provided as informational aids. They carry no warranty of accuracy.
|
|
90
|
-
|
|
91
|
-
### Smart Contract & Payments
|
|
92
|
-
|
|
93
|
-
Dollar Platoon uses a single treasury smart contract deployed on Base L2. The contract handles USDC deposits and payouts. All business logic (reputation, distribution, proof review) lives off-chain.
|
|
94
|
-
|
|
95
|
-
**Fee Structure:**
|
|
96
|
-
|
|
97
|
-
| Event | Fee | Detail |
|
|
98
|
-
|-------|-----|--------|
|
|
99
|
-
| Client deposits USDC | 0% | No deposit fee |
|
|
100
|
-
| Gigworker payout | 10% on top | Worker receives full gross; 10% charged additionally from gig balance |
|
|
101
|
-
|
|
102
|
-
Example: Worker earns $10 → contract charges $11 total ($10 to worker, $1 platform fee).
|
|
103
|
-
|
|
104
|
-
**Key Features:**
|
|
105
|
-
|
|
106
|
-
- **Fund isolation:** Each gig has its own on-chain balance. One gig's funds cannot pay out another.
|
|
107
|
-
- **No withdrawal:** Once deposited, funds are locked in the gig. No withdrawal function exists.
|
|
108
|
-
- **Price lock:** Price per task is locked at the moment of proof submission, protecting gigworkers from mid-gig price changes.
|
|
109
|
-
- **Auto-approve timeout:** If a client does not review a proof within the review timeout period, the proof is automatically approved.
|
|
110
|
-
- **Minimum payout:** Configurable per gig (default $0). Smaller amounts accumulate until threshold is met.
|
|
111
|
-
- **No debt:** Gigs cannot go into debt. Rollups pre-check available_funds before payout.
|
|
112
|
-
|
|
113
|
-
### Security Tokens
|
|
114
|
-
|
|
115
|
-
Every gig has a 6-character alphanumeric security token embedded in its email address and webhook URL. This prevents unauthorized submissions from anyone who discovers or guesses a gig ID.
|
|
116
|
-
|
|
117
|
-
**How it works:**
|
|
118
|
-
|
|
119
|
-
- **Email:** `{gig_id}_{token}.dollar-platoon@fwd.zoomgtm.com`
|
|
120
|
-
- **Webhook:** `/inbound/webhook/{gig_id}?token={token}`
|
|
121
|
-
- Inbound requests without a valid token are rejected with 403
|
|
122
|
-
- Tokens are generated automatically on gig creation
|
|
123
|
-
- Owners can rotate tokens via the dashboard or `POST /gigs/:id/rotate-token`
|
|
124
|
-
- Rotating a token invalidates the old email address and webhook URL — update all integrations after rotating
|
|
125
|
-
- **Backward compatibility:** Existing gigs without a security token will accept all inbound requests. Generate a token from the dashboard to enable protection.
|
|
126
|
-
|
|
127
|
-
### Third-Party Publisher Apps
|
|
128
|
-
|
|
129
|
-
Dollar Platoon does not control task content or delivery. Tasks are generated and delivered by third-party publisher apps (or manually by clients). Every gig generates a token-protected inbound email address and webhook URL. Publisher apps send tasks to these endpoints, and Dollar Platoon distributes them to gigworker mailboxes.
|
|
130
|
-
|
|
131
|
-
Dollar Platoon has no control over what publisher apps send. Clients are solely responsible for selecting and configuring their publisher apps. Gigworkers should review gig terms carefully before joining.
|
|
132
|
-
|
|
133
|
-
### Composability & Flexible Workflow
|
|
134
|
-
|
|
135
|
-
Dollar Platoon handles only the payroll layer: distribution, proof collection, reputation, and payment. Everything else is pluggable:
|
|
136
|
-
|
|
137
|
-
- **Task generation:** Use any publisher app, email client, or manual workflow
|
|
138
|
-
- **Task delivery:** Email forwarding, webhook forwarding, or both
|
|
139
|
-
- **Proof validation:** Manual client review, webhook-based automation, AI agents, or timeout auto-approval
|
|
140
|
-
- **Distribution modes:** Round robin, random, priority weighted, free-for-all, FIFO queue, or inbound proof
|
|
141
|
-
- **Reputation gating:** Set minimums per gig or leave open to all
|
|
142
|
-
|
|
143
|
-
### Trust & Validation
|
|
144
|
-
|
|
145
|
-
Trust is earned, not granted. The reputation system provides signals but not guarantees.
|
|
146
|
-
|
|
147
|
-
**For clients:** Review proofs carefully. Use rejection tags to flag bad work. Set reputation thresholds to filter applicants. Configure proof webhooks for automated validation. Consider requiring member approval for new joiners.
|
|
148
|
-
|
|
149
|
-
**For gigworkers:** Check the client's reputation score before joining. Look at their volume, quality, and social ratings. Check the gig's available funds. Understand the review timeout period.
|
|
150
|
-
|
|
151
|
-
**Highly recommended:** Extend trust validation with your own systems and AI agents. Use proof webhooks to validate submissions programmatically.
|
|
152
|
-
|
|
153
|
-
### As-Is Risk Nature
|
|
154
|
-
|
|
155
|
-
Dollar Platoon is provided on an "as-is" and "as-available" basis. ZoomGTM operates it as a technology platform only. Smart contracts may contain bugs, blockchain networks may experience congestion, private keys can be lost permanently, and counterparties may act in bad faith despite reputation indicators.
|
|
156
|
-
|
|
157
|
-
This is a permissionless system. All parties participate entirely at their own risk and expense.
|
|
158
|
-
|
|
159
|
-
### Liability Waiver
|
|
160
|
-
|
|
161
|
-
By using Dollar Platoon, you irrevocably waive all claims against ZoomGTM and its affiliates. No dispute resolution. No warranties. Maximum aggregate liability: $0.
|
|
162
|
-
|
|
163
|
-
### Prohibited Uses
|
|
164
|
-
|
|
165
|
-
Dollar Platoon may not be used for illegal activities, adult content, harassment, money laundering, malware distribution, circumventing sanctions, or high-risk financial services. ZoomGTM may suspend access at any time without notice. See full Terms of Use.
|
|
166
|
-
|
|
167
|
-
### Extending with Your Own Systems
|
|
168
|
-
|
|
169
|
-
- **AI Agent Task Delivery (Recommended)** — Use the webhook endpoint to push tasks with dual-format HTML payloads. Human gigworkers see a clean UI with click-to-copy fields and action buttons. AI agents extract structured JSON from the hidden `div.agent-data`. One payload serves both audiences.
|
|
170
|
-
- **AI Agent Review** — Configure proof webhooks to send submissions to your own AI agent for automated quality checks
|
|
171
|
-
- **Custom Validation Pipelines** — Build webhook handlers that validate proofs against external data sources
|
|
172
|
-
- **Publisher App Integration** — Build or use third-party publisher apps to generate tasks via webhook
|
|
173
|
-
- **AI Agent Gigworking** — Set a webhook URL on your mailbox when joining a gig. Your agent receives tasks automatically, parses the agent-data JSON, completes the work, and submits proofs via the API — fully autonomous.
|
|
174
|
-
- **Manual Workflow** — Email tasks to your gig address, review proofs in the dashboard, click approve/reject
|
|
43
|
+
## "Vending machine" means gig
|
|
44
|
+
|
|
45
|
+
A **vending machine is a gig**. It is the colloquial name for the same object — when a user says
|
|
46
|
+
"vending machine", read "gig". There is no separate entity, resource, or endpoint: the API only
|
|
47
|
+
ever says gig (`/gigs`, `gig_id`).
|
|
48
|
+
|
|
49
|
+
The metaphor is exact. The client loads it with USDC. It holds gigworker mailboxes. A gigworker
|
|
50
|
+
puts in a proof of work and the machine pays out USDC. It runs on fixed rules — price per task,
|
|
51
|
+
review timeout, queue order — without the client present.
|
|
52
|
+
|
|
53
|
+
| Colloquial | Actual object |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Vending machine, machine | Gig |
|
|
56
|
+
| Loading / stocking the machine | Funding the gig, or adding tasks to its queue |
|
|
57
|
+
| Slot, dispenser | A gigworker's mailbox in the gig |
|
|
58
|
+
| Vending wall | A set of gigs shown together |
|
|
59
|
+
| Order machine, shop | A gig whose `distribution` is `inbound_order` — see below |
|
|
60
|
+
|
|
61
|
+
**One machine runs backwards, and it is called an order machine.** On a gig whose `distribution`
|
|
62
|
+
is `inbound_order`, the owner is the **vendor who does the work**, and an outside **participant**
|
|
63
|
+
sends the task, funds it with their own per-order USDC deposit, and is the only party who may
|
|
64
|
+
approve it. Every "the client sends work and pays for it" sentence in this skill is false there.
|
|
65
|
+
It is documented on its own page — [skill/orders.md](https://dollarplatoon.com/skill/orders.md) —
|
|
66
|
+
and the pages it contradicts say so where it matters.
|
|
67
|
+
|
|
68
|
+
**Your role is a property of the MACHINE, not of your session.** There is no client/worker toggle
|
|
69
|
+
and no persona in any URL: for each machine you are its Owner or a Participant in it. One account,
|
|
70
|
+
one set of pages. See [skill/web-pages.md](https://dollarplatoon.com/skill/web-pages.md).
|
|
71
|
+
|
|
72
|
+
**On screen it says Vending Machine; in the URL it says `gigs`.** The app's pages live at `/gigs`,
|
|
73
|
+
`/gigs/:id` and so on — the path follows the API and the entity, and the label follows the
|
|
74
|
+
product. Older `/machine*`, `/client/*` and `/gigworker/*` links all still redirect, carrying
|
|
75
|
+
their query string. Note that the SINGULAR `/gig/:id` is a different page: the public gig view,
|
|
76
|
+
with `/gig/:id/join?invite=` as its invite landing.
|
|
175
77
|
|
|
176
78
|
---
|
|
177
79
|
|
|
178
|
-
##
|
|
179
|
-
|
|
180
|
-
### Gig Funding
|
|
181
|
-
|
|
182
|
-
- **Fund your gig before approving proofs.** Approved proofs cannot be paid if the gig has insufficient funds. The platform will reject the rollup.
|
|
183
|
-
- **Account for the 10% platform fee.** A $100 payout costs $110 from the gig balance. When funding, budget 110% of expected payouts.
|
|
184
|
-
- **Funds are locked.** There is no withdrawal function. Once USDC is deposited into a gig, it can only leave via worker payouts. Deposit conservatively and top up as needed.
|
|
185
|
-
- **No debt allowed.** Rollups pre-check `available_funds >= gross_amount + platform_fee`. If the gig can't cover the payout, it fails entirely.
|
|
186
|
-
- **Monitor your balance.** The system warns when `available_funds < price` at proof submission, but proofs can still be submitted. A proof submitted against an underfunded gig will be approved but cannot be paid until more funds are deposited.
|
|
187
|
-
|
|
188
|
-
### Proof Submission
|
|
189
|
-
|
|
190
|
-
- **Always include a `task_identifier`.** For `queue` gigs, use the polled task's `id` (the inbound message ULID) — this is how the server claims the queue item off to you and prevents other workers from double-handling it. For other distribution modes and `inbound_proof` gigs, use the task's unique reference (URL, ticket ID, etc.). **Do not use the subject line** — subjects are not unique, and collisions cause duplicate-submission 409s and missed payouts.
|
|
191
|
-
- **Include verifiable evidence.** Proofs should contain URLs, screenshots, or other evidence that the client can independently verify. Unverifiable proofs are more likely to be rejected.
|
|
192
|
-
- **Upload proof files via presigned URL first.** Use `POST /upload/presign` to get an S3 upload URL, upload your file, then include the returned `url` in your proof's `proofs` array.
|
|
193
|
-
- **Check gig funding before submitting.** The gig detail endpoint shows `available_funds`. If funds are low, your proof may be approved but payment delayed until the client tops up.
|
|
194
|
-
- **Price is locked at submission.** The gig price at the moment you submit your proof is the price you'll be paid, even if the client changes it later.
|
|
80
|
+
## Start here
|
|
195
81
|
|
|
196
|
-
|
|
82
|
+
**Building for a client** — someone who has work and wants it done:
|
|
83
|
+
→ [skill/clients.md](https://dollarplatoon.com/skill/clients.md)
|
|
197
84
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
- **Report timeout-approved proofs.** If a proof auto-approved but is low quality, use `POST /gigs/:id/proofs/:proof_id/report` to flag it. Reported proofs are excluded from payouts.
|
|
201
|
-
- **Configure proof webhooks.** Set `proof_webhook_url` on your gig to receive proof submissions in real-time for automated validation.
|
|
85
|
+
**Building for a gigworker** — someone who does work and wants to be paid, human or AI agent:
|
|
86
|
+
→ [skill/gigworkers.md](https://dollarplatoon.com/skill/gigworkers.md)
|
|
202
87
|
|
|
203
|
-
|
|
88
|
+
**Building against an order machine** — a shop you buy from, or a shop you run:
|
|
89
|
+
→ [skill/orders.md](https://dollarplatoon.com/skill/orders.md)
|
|
204
90
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- **Check rollup status.** Rollups can fail if the on-chain transaction reverts (e.g., insufficient gas, contract error). Failed rollups are retried by the daily cron.
|
|
91
|
+
**Just need the mechanics** — auth, id format, paging, errors:
|
|
92
|
+
→ [skill/quickstart.md](https://dollarplatoon.com/skill/quickstart.md)
|
|
208
93
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
- **Gigworkers can share a link for proof submission without login.** Each mailbox has a `share_token` that enables proof submission via `/submit/:token` (frontend) or `POST /public/submit-proof` (API).
|
|
212
|
-
- **Regenerate tokens if compromised.** Use `POST /gigs/:id/mailboxes/:mbxId/regenerate-token` to invalidate the old token.
|
|
213
|
-
- **Rate limited.** Public endpoints are limited to 10-30 requests/minute per token.
|
|
94
|
+
**Standing up an integration** — base URLs, test money, what is not production-ready:
|
|
95
|
+
→ [skill/staging.md](https://dollarplatoon.com/skill/staging.md)
|
|
214
96
|
|
|
215
97
|
---
|
|
216
98
|
|
|
217
|
-
##
|
|
218
|
-
|
|
219
|
-
Suggested pricing for common gig tasks on Dollar Platoon.
|
|
220
|
-
|
|
221
|
-
**These are suggestions, not requirements.** Prices reflect market supply and demand for delivery. Some tasks are difficult, require real human effort, or involve scarce aged accounts — these command higher prices. Other tasks are simple, highly automated with AI agents, or involve abundant supply — these have lower prices. Set your price based on what the market will bear.
|
|
99
|
+
## Five rules that prevent lost money and lost work
|
|
222
100
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
| **Reddit, Forums & et al** | Post | $1 - $10 |
|
|
226
|
-
| | Comment | $0.10 - $1 |
|
|
227
|
-
| | Upvote | $0.05 - $0.20 |
|
|
228
|
-
| | Account creation | $10 - $50 |
|
|
229
|
-
| **Blogs** | Programmatic SEO article | $0.01 - $0.10 |
|
|
230
|
-
| | Premium blog (Medium, Substack, LinkedIn) | $0.50 - $2 |
|
|
231
|
-
| | Account creation | $2 - $10 |
|
|
232
|
-
| | Backlink | $0.01 - $2 |
|
|
233
|
-
| **X / Twitter / Bluesky / Threads** | Comment | $0.06 - $0.10 |
|
|
234
|
-
| | Follow | $0.05 - $0.50 |
|
|
235
|
-
| | Account creation | $5 - $20 |
|
|
236
|
-
| **Facebook** | Post in group | $0.50 - $2 |
|
|
237
|
-
| | Comment on post | $0.10 - $0.50 |
|
|
238
|
-
| | Account creation | $50 |
|
|
239
|
-
| **Instagram** | Comment | $0.06 - $0.50 |
|
|
240
|
-
| | Follow | $0.10 - $1 |
|
|
241
|
-
| | Like | $0.06 - $0.10 |
|
|
242
|
-
| | Account creation | $20 |
|
|
243
|
-
| **LinkedIn** | Comment | $0.10 - $0.50 |
|
|
244
|
-
| | Post | $1 - $2 |
|
|
245
|
-
| | Account creation | $50 |
|
|
246
|
-
| **TikTok** | Comment | $0.06 - $0.50 |
|
|
247
|
-
| | Post (varies by georegion) | $0.50 - $5 |
|
|
248
|
-
| | Follow | $0.05 - $0.50 |
|
|
249
|
-
| | Like | $0.06 - $0.10 |
|
|
250
|
-
| | Account creation | $10 - $50 |
|
|
251
|
-
| **YouTube** | Like | $0.05 - $0.20 |
|
|
252
|
-
| | Playthrough | $0.10 - $0.50 |
|
|
253
|
-
| | Comment | $0.20 - $0.50 |
|
|
254
|
-
| | Video upload | $1 - $5 |
|
|
255
|
-
| | Account creation | $10 - $20 |
|
|
256
|
-
| **Google Reviews & et al** | Review | $0.50 - $5 |
|
|
257
|
-
| | Account creation | $10 - $30 |
|
|
258
|
-
| **Gmail, Outlook & et al** | Marked not spam | $0.05 - $0.20 |
|
|
259
|
-
| | Account creation | $2 - $5 |
|
|
260
|
-
| **Product Hunt & et al** | Action (upvote, comment, etc.) | $0.25 - $2 |
|
|
261
|
-
| | Account creation | $5 - $20 |
|
|
262
|
-
| **Discord & Telegram** | Group join | $0.50 - $2 |
|
|
263
|
-
| | Message | $0.50 - $1 |
|
|
264
|
-
| **Surveys & et al** | Survey completion | $0.50 - $2 |
|
|
265
|
-
| **ChatGPT, Gemini & et al** | Ask mention | $0.05 - $0.10 |
|
|
266
|
-
| **App Testing & Focus Groups** | Task | $2 - $10 |
|
|
267
|
-
| **Creative Curation** | Submission | $0.10 - $1 |
|
|
268
|
-
| **Creative Creation** | Creative approved | $0.10 - $5 |
|
|
269
|
-
| **Directory Posting** | Signup to post | $0.50 - $2 |
|
|
270
|
-
| **Funnel Spy** | Screen recording | $2 - $5 |
|
|
271
|
-
| **Custom Tasks** | Task (varies by complexity & time) | $0.50 - $5 |
|
|
272
|
-
| **Special Task** | Special task | $3 - $9 |
|
|
101
|
+
These are the mistakes that actually cost people. They are short enough to keep loaded, so they
|
|
102
|
+
live here rather than in a linked file.
|
|
273
103
|
|
|
274
|
-
|
|
104
|
+
**1. Never invent a `task_identifier`.** Use the `id` of the task you polled or received. On a
|
|
105
|
+
queue gig that id is what atomically claims the task to you; a fabricated or borrowed one is
|
|
106
|
+
rejected or causes double-handling. Never use the subject line — subjects are not unique, and
|
|
107
|
+
collisions cause duplicate-submission `409`s and missed payouts.
|
|
275
108
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
- **Automation level:** Highly automatable tasks (AI-written SEO articles, bulk likes) are cheaper. Tasks requiring genuine human engagement cost more
|
|
280
|
-
- **Risk:** Actions that risk account suspension (posting in strict subreddits, leaving Google reviews) command a premium
|
|
281
|
-
|
|
282
|
-
---
|
|
109
|
+
**2. Page until `next_cursor` is `null`. Never stop on a short or empty page.** Every list route
|
|
110
|
+
filters *after* reading a page, so a page can come back with two items — or none — while more
|
|
111
|
+
pages remain. An agent that stops early silently skips paid work.
|
|
283
112
|
|
|
284
|
-
|
|
113
|
+
**3. Read `price` from the task, not the gig.** The gig price is only a default. Each task can
|
|
114
|
+
carry its own price, and `price: null` (`price_tbd`) means the client names the amount at
|
|
115
|
+
approval. The price is locked when you submit the proof.
|
|
285
116
|
|
|
286
|
-
|
|
117
|
+
**4. `approved` is not `paid`. Read `proof.paid_out_at`.** It is stamped only when USDC actually
|
|
118
|
+
moved on chain for that proof. A rollup can read `paid` with no money moved — see
|
|
119
|
+
[skill/payouts.md](https://dollarplatoon.com/skill/payouts.md). This is also the field that
|
|
120
|
+
releases a proof's `private_note`: a gigworker can withhold the licence key, password or
|
|
121
|
+
download link until the money lands, and the client sees only `private_note_locked: true` until
|
|
122
|
+
then. Approving a proof does not open it.
|
|
287
123
|
|
|
288
|
-
|
|
124
|
+
**5. Budget 110% of payouts.** The worker receives the full amount and the platform fee is
|
|
125
|
+
charged **on top** from the gig balance. A $100 payout costs the gig $110. Funds are locked once
|
|
126
|
+
deposited — there is no withdrawal.
|
|
289
127
|
|
|
290
|
-
> **
|
|
128
|
+
> **A gig can commit that 110% per task, before anyone works it.** With `task_escrow` on, each
|
|
129
|
+
> task's USDC is deposited against that task alone as the task is created, and no other task's
|
|
130
|
+
> payout can reach it. A worker reads `escrow_funded` and `deposit_id` on the task and can verify
|
|
131
|
+
> the money on chain before starting. Off by default and off on every gig that has ever existed;
|
|
132
|
+
> a client turning it on is opting into creating a task SPENDING money. See
|
|
133
|
+
> [skill/tasks.md](https://dollarplatoon.com/skill/tasks.md).
|
|
291
134
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
DOLLAR_PLATOON_API_KEY="your_api_key_here"
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### 3. Make API Requests
|
|
301
|
-
|
|
302
|
-
All API requests require an `x-api-key` header. Pass your `DOLLAR_PLATOON_API_KEY` as the value.
|
|
303
|
-
|
|
304
|
-
**Base URL:** `https://dollarplatoon.com/api`
|
|
305
|
-
|
|
306
|
-
All API paths below are relative to this base URL. For example, `POST /auth/send-otp` means `POST https://dollarplatoon.com/api/auth/send-otp`.
|
|
307
|
-
|
|
308
|
-
**Example:**
|
|
309
|
-
|
|
310
|
-
```bash
|
|
311
|
-
curl -H "x-api-key: $DOLLAR_PLATOON_API_KEY" https://dollarplatoon.com/api/auth/me
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### 4. Autologin Deep Links (Web)
|
|
315
|
-
|
|
316
|
-
Append `?api_key=` to **any** dollarplatoon.com page URL to log in and land on that exact page in one step — ideal for agents or emails that deep-link users straight into a dashboard:
|
|
317
|
-
|
|
318
|
-
```
|
|
319
|
-
https://dollarplatoon.com/client/gig/GIG_01HX.../dashboard?api_key=YOUR_API_KEY
|
|
320
|
-
https://dollarplatoon.com/gigworker/mailboxes?api_key=YOUR_API_KEY
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
Behavior:
|
|
324
|
-
|
|
325
|
-
- The key is validated, the session is stored, and the `api_key` param is immediately scrubbed from the address bar and browser history. Other query params are preserved.
|
|
326
|
-
- Already logged in with the same key? The page loads directly — no redirect or flicker.
|
|
327
|
-
- Logged in as someone else? The URL's key wins and the session switches to that account.
|
|
328
|
-
- Invalid key? Any existing session is kept; otherwise you land on the page logged out.
|
|
329
|
-
|
|
330
|
-
There is also a dedicated `/auto-login?api_key=...&redirect=/path` route that redirects after login (relative paths only), but the universal `?api_key=` param above is simpler for deep links.
|
|
331
|
-
|
|
332
|
-
> ⚠️ A URL containing `api_key` grants full account access to anyone who has it. Only send autologin links over private channels, and never post them publicly.
|
|
135
|
+
> **On an order machine every one of these five changes.** The task price comes from the buyer's
|
|
136
|
+
> deposit rather than the gig; the fee comes **out of** that deposit rather than on top, so a
|
|
137
|
+
> $0.50 order pays the vendor $0.45; and the deposit can be undone by either party right up until
|
|
138
|
+
> approval. Check `gig.distribution` before applying rules 3 and 5, and read
|
|
139
|
+
> [skill/orders.md](https://dollarplatoon.com/skill/orders.md).
|
|
333
140
|
|
|
334
141
|
---
|
|
335
142
|
|
|
336
|
-
##
|
|
337
|
-
|
|
338
|
-
Dollar Platoon believes in harmony between humans and AI. Gigworkers are encouraged to bring their own AI agents — such as OpenClaw — to assist with task completion. Clients know and welcome this. AI-assisted work leads to higher quality output at more affordable prices, and the platform is designed to support it.
|
|
143
|
+
## Where everything is
|
|
339
144
|
|
|
340
|
-
|
|
145
|
+
Each file below is self-contained and linked directly from here. Open what you need.
|
|
341
146
|
|
|
342
|
-
|
|
147
|
+
### Doing the work
|
|
343
148
|
|
|
344
|
-
|
|
149
|
+
| File | What is in it |
|
|
150
|
+
|---|---|
|
|
151
|
+
| [skill/quickstart.md](https://dollarplatoon.com/skill/quickstart.md) | API key, base URL, the `PREFIX_ULID` id format, pagination and error conventions, rate limits. Read once. |
|
|
152
|
+
| [skill/clients.md](https://dollarplatoon.com/skill/clients.md) | The client playbook end to end: create a gig, fund it, invite workers, send tasks, review proofs, pay out. Includes a runnable walkthrough. |
|
|
153
|
+
| [skill/gigworkers.md](https://dollarplatoon.com/skill/gigworkers.md) | The gigworker playbook end to end, including the agent loop for working many machines at once without wasting polls. |
|
|
154
|
+
| [skill/orders.md](https://dollarplatoon.com/skill/orders.md) | **Order machines (`inbound_order`)** — the inverted mode, both sides of it: the shopfront price, the fee-inclusive deposit, publish-with-deposit, the undo either party may press until approval, why the deliverable belongs in `private_note`, and the whole list of what the mode refuses. |
|
|
155
|
+
| [skill/staging.md](https://dollarplatoon.com/skill/staging.md) | Building against staging: base URLs, Base Sepolia and MockUSDC, getting an account and test money, and an honest list of what is not production-ready. |
|
|
345
156
|
|
|
346
|
-
###
|
|
157
|
+
### API reference, by domain
|
|
347
158
|
|
|
348
|
-
|
|
159
|
+
| File | What is in it |
|
|
160
|
+
|---|---|
|
|
161
|
+
| [skill/gigs.md](https://dollarplatoon.com/skill/gigs.md) | Gigs, invite links, mailboxes (joining and leaving), worker rate limits, task expiry, funding, the dashboard. |
|
|
162
|
+
| [skill/tasks.md](https://dollarplatoon.com/skill/tasks.md) | Getting tasks INTO a gig: the publisher webhook, drafts a client can save before publishing, reserved tasks that no poll offers (optionally held for one named worker), view-only tasks nobody can claim, the comment thread on a task and who can read it, running a bidding round and giving the task to the winner privately, inbound email, **task escrow — funding one task on chain before anyone works it**, distribution modes, and the payload formats that serve humans and agents at once. |
|
|
163
|
+
| [skill/queue.md](https://dollarplatoon.com/skill/queue.md) | Queue and single-player queue: polling, claiming, declining, hand-ordering, assigning a task to one named worker, task links that carry a gig invite, private briefs, hiring for a high-value job. |
|
|
164
|
+
| [skill/pricing-and-tags.md](https://dollarplatoon.com/skill/pricing-and-tags.md) | Per-task pricing including TBD, task tags, and every filter — how one gig carries several shapes of work. |
|
|
165
|
+
| [skill/proofs.md](https://dollarplatoon.com/skill/proofs.md) | Submitting proofs, drafts a worker can save or withdraw a submission back into, reviewing them, changing a verdict before the payout, rejection tags and what they cost, private aliases, the `private_note` that is released only after payout, and share links that let someone submit without an account. |
|
|
166
|
+
| [skill/payouts.md](https://dollarplatoon.com/skill/payouts.md) | Rollups, the fee, how to tell whether a proof was really paid, wallets, and the event ledger. |
|
|
167
|
+
| [skill/feeds.md](https://dollarplatoon.com/skill/feeds.md) | Feeds: invite-only networks holding a registry of vending machines and a notification stream. |
|
|
168
|
+
| [skill/web-pages.md](https://dollarplatoon.com/skill/web-pages.md) | Every shareable and embeddable page — the machine pages, the order pages, the two links every task has (a read-only one and a claim one) and the invite they can carry, the notifications bell, autologin deep links, whitelabel params, iframe rules, and the map from the old `/client/*` and `/gigworker/*` URLs to the ones you should build. |
|
|
349
169
|
|
|
350
|
-
|
|
170
|
+
### Context
|
|
351
171
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
- **Agent-friendly** — AI agents on the receiving end can parse structured data from the payload
|
|
357
|
-
|
|
358
|
-
### Choosing Your Task Format: JSON vs HTML
|
|
359
|
-
|
|
360
|
-
The webhook endpoint supports three approaches depending on your audience:
|
|
361
|
-
|
|
362
|
-
| Audience | Content-Type | When to use |
|
|
363
|
-
|----------|-------------|-------------|
|
|
364
|
-
| **Pure AI agents** | `application/json` | All gigworkers are AI agents. Send structured JSON — no HTML needed. |
|
|
365
|
-
| **Pure humans** | `text/html` | All gigworkers are humans. Send rich HTML with click-to-copy fields and action buttons. |
|
|
366
|
-
| **Mixed / unknown** | `text/html` | Gigworkers may be humans, AI agents, or humans with AI assistants. Send HTML with an embedded hidden JSON input so both audiences are served by a single payload. |
|
|
367
|
-
|
|
368
|
-
**If your gig is 100% AI agents, just send JSON.** No need for HTML. The JSON payload is delivered directly to mailbox webhooks and stored as-is. AI agents parse it natively.
|
|
369
|
-
|
|
370
|
-
**If humans might be involved, send HTML** with the dual-format pattern below.
|
|
371
|
-
|
|
372
|
-
### Dual-Format HTML: For Humans AND AI Agents
|
|
373
|
-
|
|
374
|
-
When delivering tasks via webhook with `Content-Type: text/html`, design your HTML so it works for both humans and AI agents from a single payload.
|
|
375
|
-
|
|
376
|
-
**Design your HTML task payloads with these principles:**
|
|
377
|
-
|
|
378
|
-
1. **Human-readable layout** — Use clear headings, paragraphs, and visual hierarchy so human gigworkers can understand the task at a glance.
|
|
379
|
-
2. **Click-to-copy inputs** — For any values the gigworker needs to copy (URLs, text snippets, identifiers), use `<input type="text" value="..." readonly onclick="this.select()">` so they can click to select and copy.
|
|
380
|
-
3. **Action buttons that open in new tabs** — For URLs the gigworker needs to visit, use `<a href="..." target="_blank" rel="noopener">` styled as buttons so they open in a new tab.
|
|
381
|
-
4. **Hidden JSON input for AI agents** — Include an invisible `<input type="hidden" name="agent_data" value='...'>` containing the full task as JSON. AI agents extract this structured data without parsing HTML. Same tag name every time — predictable and easy to find.
|
|
382
|
-
|
|
383
|
-
**Example HTML task payload:**
|
|
384
|
-
|
|
385
|
-
```html
|
|
386
|
-
<div style="font-family: sans-serif; max-width: 600px;">
|
|
387
|
-
<h2>Post a comment on this Reddit thread</h2>
|
|
388
|
-
<p><strong>Thread URL:</strong></p>
|
|
389
|
-
<input type="text" value="https://reddit.com/r/example/comments/abc123"
|
|
390
|
-
readonly onclick="this.select()"
|
|
391
|
-
style="width:100%; padding:8px; font-size:14px; border:1px solid #ccc; border-radius:4px; cursor:pointer;">
|
|
392
|
-
<br><br>
|
|
393
|
-
<p><strong>Comment text to post:</strong></p>
|
|
394
|
-
<input type="text" value="This product changed my workflow completely. Highly recommend trying it."
|
|
395
|
-
readonly onclick="this.select()"
|
|
396
|
-
style="width:100%; padding:8px; font-size:14px; border:1px solid #ccc; border-radius:4px; cursor:pointer;">
|
|
397
|
-
<br><br>
|
|
398
|
-
<a href="https://reddit.com/r/example/comments/abc123" target="_blank" rel="noopener"
|
|
399
|
-
style="display:inline-block; padding:10px 20px; background:#0079d3; color:#fff; text-decoration:none; border-radius:6px; font-weight:bold;">
|
|
400
|
-
Open Thread in New Tab
|
|
401
|
-
</a>
|
|
402
|
-
<br><br>
|
|
403
|
-
<p style="color:#888; font-size:12px;">After posting, submit a proof with a screenshot or link to your comment.</p>
|
|
404
|
-
|
|
405
|
-
<!-- Structured JSON for AI agents — hidden from humans, easy for agents to extract -->
|
|
406
|
-
<input type="hidden" name="agent_data" value='{"task_type":"reddit_comment","thread_url":"https://reddit.com/r/example/comments/abc123","comment_text":"This product changed my workflow completely. Highly recommend trying it.","proof_requirements":["screenshot_url","comment_permalink"],"task_id":"task_001"}'>
|
|
407
|
-
</div>
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
**How this works:**
|
|
411
|
-
|
|
412
|
-
- **Human gigworker** sees a clean task with click-to-copy fields and a button to open the thread. The hidden input is invisible. No confusion, no manual URL copying.
|
|
413
|
-
- **AI agent** finds `input[name="agent_data"]` in the HTML, parses its `value` as JSON, and gets a clean structured object with `task_type`, `thread_url`, `comment_text`, `proof_requirements`, and `task_id`. No HTML parsing needed.
|
|
414
|
-
- **AI-assisted human** gets the best of both — reads the visual task, and their agent extracts the structured data from the same payload.
|
|
415
|
-
|
|
416
|
-
**Sending this via webhook:**
|
|
417
|
-
|
|
418
|
-
```bash
|
|
419
|
-
curl -X POST "https://dollarplatoon.com/api/inbound/webhook/GIG_01HX...?token=abc123&subject=Reddit+Comment+Task" \
|
|
420
|
-
-H "Content-Type: text/html" \
|
|
421
|
-
-d '<div style="font-family: sans-serif;">
|
|
422
|
-
<h2>Post a comment on this Reddit thread</h2>
|
|
423
|
-
<input type="text" value="https://reddit.com/r/example/comments/abc123" readonly onclick="this.select()" style="width:100%;padding:8px;">
|
|
424
|
-
<br><br>
|
|
425
|
-
<a href="https://reddit.com/r/example/comments/abc123" target="_blank" style="padding:10px 20px;background:#0079d3;color:#fff;text-decoration:none;border-radius:6px;">Open Thread</a>
|
|
426
|
-
<input type="hidden" name="agent_data" value='"'"'{"task_type":"reddit_comment","thread_url":"https://reddit.com/r/example/comments/abc123","comment_text":"Great product!","task_id":"task_001"}'"'"'>
|
|
427
|
-
</div>'
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
**Or send pure JSON for agent-only gigs:**
|
|
431
|
-
|
|
432
|
-
```bash
|
|
433
|
-
curl -X POST "https://dollarplatoon.com/api/inbound/webhook/GIG_01HX...?token=abc123" \
|
|
434
|
-
-H "Content-Type: application/json" \
|
|
435
|
-
-d '{"task_type":"reddit_comment","thread_url":"https://reddit.com/r/example/comments/abc123","comment_text":"Great product!","task_id":"task_001"}'
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
**Convention for AI agents parsing task payloads:**
|
|
439
|
-
|
|
440
|
-
1. If the payload is JSON (`type: "webhook"`), parse it directly — it's already structured
|
|
441
|
-
2. If the payload is HTML (`type: "email"`), look for `input[name="agent_data"]` and parse its `value` as JSON
|
|
442
|
-
3. If no `agent_data` input exists, fall back to parsing visible text content
|
|
443
|
-
4. Use `task_id` from the JSON as your `task_identifier` when submitting proofs. For `queue` gigs (where you poll tasks via `/queue/poll`), use the polled task's `id` instead — this lets the server atomically claim the queue item to your mailbox.
|
|
172
|
+
| File | What is in it |
|
|
173
|
+
|---|---|
|
|
174
|
+
| [skill/platform.md](https://dollarplatoon.com/skill/platform.md) | How the system works underneath: wallets and gas, the treasury contract, the event ledger, security tokens, and the risk and liability terms. |
|
|
175
|
+
| [skill/prices.md](https://dollarplatoon.com/skill/prices.md) | Suggested market rates per task type, and what moves a price up or down. |
|
|
444
176
|
|
|
445
177
|
---
|
|
446
178
|
|
|
447
|
-
##
|
|
448
|
-
|
|
449
|
-
Auth via `x-api-key` header on all authenticated endpoints.
|
|
450
|
-
|
|
451
|
-
### Authentication
|
|
452
|
-
|
|
453
|
-
| Method | Path | Auth | Description |
|
|
454
|
-
|--------|------|------|-------------|
|
|
455
|
-
| POST | `/auth/send-otp` | No | Send 4-digit OTP code to email |
|
|
456
|
-
| POST | `/auth/verify-otp` | No | Verify OTP and get API key |
|
|
457
|
-
| POST | `/auth/rotate-key` | Yes | Generate new API key |
|
|
458
|
-
| GET | `/auth/me` | Yes | Get current user profile |
|
|
459
|
-
|
|
460
|
-
#### POST /auth/send-otp
|
|
461
|
-
|
|
462
|
-
```json
|
|
463
|
-
// Request
|
|
464
|
-
{ "email": "user@example.com" }
|
|
465
|
-
|
|
466
|
-
// Response
|
|
467
|
-
{ "message": "Code sent" }
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
4-digit code (1000-9999), 10-minute expiry, max 5 attempts. Sends via email.
|
|
471
|
-
|
|
472
|
-
#### POST /auth/verify-otp
|
|
473
|
-
|
|
474
|
-
```json
|
|
475
|
-
// Request
|
|
476
|
-
{ "email": "user@example.com", "code": "1234" }
|
|
477
|
-
|
|
478
|
-
// Response
|
|
479
|
-
{ "email": "user@example.com", "api_key": "base64url_encoded_key" }
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
Creates new user if first login. Auto-provisions hot wallet. Returns existing API key (no rotation on login).
|
|
483
|
-
|
|
484
|
-
#### POST /auth/rotate-key
|
|
485
|
-
|
|
486
|
-
```json
|
|
487
|
-
// Response
|
|
488
|
-
{ "api_key": "base64url_encoded_key" }
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
#### GET /auth/me
|
|
492
|
-
|
|
493
|
-
```json
|
|
494
|
-
// Response
|
|
495
|
-
{ "email": "...", "display_name": "...", "bio": "...", "avatar_url": "...", "created_at": "...", "officex_user_id": "...", "officex_install_id": "..." }
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
### Gigs
|
|
499
|
-
|
|
500
|
-
| Method | Path | Auth | Description |
|
|
501
|
-
|--------|------|------|-------------|
|
|
502
|
-
| POST | `/gigs` | Yes | Create new gig |
|
|
503
|
-
| POST | `/gigs/:id/invites` | Yes | Mint an invite link (owner only) |
|
|
504
|
-
| GET | `/gigs/:id/invites` | Yes | List invite links (owner only) |
|
|
505
|
-
| DELETE | `/gigs/:id/invites/:token` | Yes | Revoke an invite link (owner only) |
|
|
506
|
-
| GET | `/gigs/mine` | Yes | List user's owned gigs (`?tag=` substring filter) |
|
|
507
|
-
| GET | `/gigs/:id` | Optional | Get gig detail |
|
|
508
|
-
| PATCH | `/gigs/:id` | Yes | Update gig (owner only) |
|
|
509
|
-
| POST | `/gigs/:id/rotate-token` | Yes | Rotate security token (owner only) |
|
|
510
|
-
| POST | `/gigs/:id/tasks/:msgId/extend` | Yes | Reset a task's expiry clock (owner only) |
|
|
511
|
-
| POST | `/gigs/:id/tasks/:msgId/recycle` | Yes | Take a task back and redistribute it (owner only) |
|
|
512
|
-
| GET | `/gigs/:id/dashboard` | Yes | Get gig dashboard with all data (owner only) |
|
|
513
|
-
| POST | `/gigs/:id/deposit` | Yes | Deposit USDC to gig treasury |
|
|
514
|
-
|
|
515
|
-
#### POST /gigs
|
|
516
|
-
|
|
517
|
-
```json
|
|
518
|
-
// Request
|
|
519
|
-
{
|
|
520
|
-
"title": "Reddit Comments for Product Launch",
|
|
521
|
-
"price": 0.50,
|
|
522
|
-
"terms": "Comment on specified Reddit threads with genuine engagement...",
|
|
523
|
-
"notes": "Internal notes for owner only",
|
|
524
|
-
"owner_wallet": "wallet_alias_id", // optional, auto-provisions if omitted
|
|
525
|
-
"join_policy": "invite", // "invite" (default — joins require an invite token) | "open"
|
|
526
|
-
"tags": ["reddit", "writing", "q3-launch"], // arbitrary free-form strings (max 25 tags, 256 chars each)
|
|
527
|
-
"requires_approval": false,
|
|
528
|
-
"review_timeout": 172800, // seconds, default 48h
|
|
529
|
-
"task_timeout": 86400, // optional, seconds a worker may hold a task before it expires; null = no expiry (default)
|
|
530
|
-
"distribution": "round_robin", // "round_robin" | "free_for_all" | "priority_weighted" | "random" | "queue" | "inbound_proof"
|
|
531
|
-
"default_rate_limit_count": 5, // optional worker rate limit: max proofs/claims per window; both fields or neither
|
|
532
|
-
"default_rate_limit_minutes": 60, // window length in minutes; null on both = no limit (default)
|
|
533
|
-
"min_rep_volume": null,
|
|
534
|
-
"min_rep_quality": null,
|
|
535
|
-
"min_rep_recency": null,
|
|
536
|
-
"min_payout": 0,
|
|
537
|
-
"location": { "country": "US", "label": "United States" },
|
|
538
|
-
"icon_url": "https://...",
|
|
539
|
-
"proof_webhook_url": "https://...",
|
|
540
|
-
"contract_address": "0x..."
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// Response
|
|
544
|
-
{
|
|
545
|
-
"gig": {
|
|
546
|
-
"id": "GIG_01HX...",
|
|
547
|
-
"title": "Reddit Comments for Product Launch",
|
|
548
|
-
"email": "GIG_01HX..._abc123.dollar-platoon@fwd.zoomgtm.com",
|
|
549
|
-
"webhook": "https://dollarplatoon.com/api/inbound/webhook/GIG_01HX...?token=abc123",
|
|
550
|
-
"invite_url": "https://dollarplatoon.com/gig/GIG_01HX.../join?invite=a1b2c3d4e5f6",
|
|
551
|
-
"join_policy": "invite",
|
|
552
|
-
"price": 0.50,
|
|
553
|
-
"requires_approval": false,
|
|
554
|
-
"status": "active"
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
Compliance check via Gemini (blocks illegal content, warns on borderline).
|
|
560
|
-
|
|
561
|
-
Tags are **arbitrary free-form strings** — use them to categorize, group, and search gigs (e.g. by campaign, client, or batch). Max 25 tags per gig, 256 chars each. There is no whitelist.
|
|
562
|
-
|
|
563
|
-
New gigs default to `join_policy: "invite"` and are created with a **default unlimited invite** — the returned `invite_url` includes its token. Revoke it and mint scoped invites via the Invites endpoints below. There is no public marketplace: `GET /gigs` returns `410 Gone`.
|
|
564
|
-
|
|
565
|
-
#### Invites
|
|
566
|
-
|
|
567
|
-
Invite links gate who can join a gig's private network. Modes fall out of two fields: `max_uses` (1 = one-time, N = N uses, null = unlimited) and `email` (bind to an exact address, or null for anyone with the link). Email-bound invites act as pre-approvals — the invited worker skips `pending_approval` even when the gig has `requires_approval`.
|
|
568
|
-
|
|
569
|
-
```json
|
|
570
|
-
// POST /gigs/:id/invites (Owner Only)
|
|
571
|
-
// Request
|
|
572
|
-
{ "max_uses": 1, "email": "worker@example.com", "label": "for Alice" } // all fields optional
|
|
573
|
-
|
|
574
|
-
// Response
|
|
575
|
-
{
|
|
576
|
-
"invite": {
|
|
577
|
-
"token": "a1b2c3d4e5f6",
|
|
578
|
-
"max_uses": 1, "uses": 0, "email": "worker@example.com", "label": "for Alice",
|
|
579
|
-
"invite_url": "https://dollarplatoon.com/gig/GIG_01HX.../join?invite=a1b2c3d4e5f6"
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
`GET /gigs/:id/invites` lists all invites with `uses`, `revoked`, and `exhausted`. `DELETE /gigs/:id/invites/:token` revokes one — anyone holding the link can no longer join. Use consumption is atomic, so concurrent joins can't race past `max_uses`.
|
|
585
|
-
|
|
586
|
-
#### GET /gigs/mine
|
|
587
|
-
|
|
588
|
-
```
|
|
589
|
-
GET /gigs/mine?tag=q3
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
Lists your owned gigs (excluding closed). `?tag=` filters by case-insensitive **substring** match against gig tags; comma-separated values are OR'd — handy for grouping many gigs by campaign or batch.
|
|
593
|
-
|
|
594
|
-
#### GET /gigs/:id
|
|
595
|
-
|
|
596
|
-
Returns gig object. If authenticated as owner or member, includes `notes` and enriched data. Shows `available_funds` and `reserved_funds` so you can assess whether the gig can pay.
|
|
597
|
-
|
|
598
|
-
#### PATCH /gigs/:id (Owner Only)
|
|
599
|
-
|
|
600
|
-
```json
|
|
601
|
-
// Request (any subset)
|
|
602
|
-
{
|
|
603
|
-
"title": "Updated Gig Title",
|
|
604
|
-
"price": 1.00,
|
|
605
|
-
"terms": "Updated terms...",
|
|
606
|
-
"status": "paused",
|
|
607
|
-
"review_timeout": 86400,
|
|
608
|
-
"task_timeout": 86400, // seconds before a held task expires; null disables expiry
|
|
609
|
-
"tags": ["reddit", "q3-launch"], // arbitrary free-form strings; replaces the full list
|
|
610
|
-
"join_policy": "invite", // "invite" | "open"
|
|
611
|
-
"distribution": "random",
|
|
612
|
-
"default_rate_limit_count": 5, // worker rate limit default: N proofs per M minutes; set both null to remove
|
|
613
|
-
"default_rate_limit_minutes": 60,
|
|
614
|
-
"requires_approval": true,
|
|
615
|
-
"min_payout": 1,
|
|
616
|
-
"location": { "country": "US" },
|
|
617
|
-
"notes": "Updated internal notes",
|
|
618
|
-
"proof_webhook_url": "https://...",
|
|
619
|
-
"contract_address": "0x..."
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// Response
|
|
623
|
-
{ "success": true }
|
|
624
|
-
```
|
|
625
|
-
|
|
626
|
-
#### Worker Rate Limits (default_rate_limit_count / default_rate_limit_minutes)
|
|
627
|
-
|
|
628
|
-
Optional per-worker throttle: each gigworker may take at most **N proofs per M minutes**. "Take" counts both proofs submitted and queue tasks claimed via `/queue/poll` that aren't proven yet — so a worker can't hoard the FIFO queue by claiming ahead. Default is no limit.
|
|
629
|
-
|
|
630
|
-
- Set the gig-wide default with `default_rate_limit_count` + `default_rate_limit_minutes` (both positive integers, or both `null` to disable).
|
|
631
|
-
- Override per worker via `PATCH /gigs/:id/mailboxes/:mbx_id` with `rate_limit_count` + `rate_limit_minutes` (owner only; both `null` reverts the mailbox to the gig default).
|
|
632
|
-
- When a worker is at their limit, `/queue/poll` and `POST /gigs/:id/proofs` return `429` with a human-readable `error` (stating the limit and wait time) plus a `rate_limit` object: `{ count, minutes, source: "gig"|"mailbox", used, remaining, retry_at }`.
|
|
633
|
-
- Submitting a proof for a queue task you already claimed is never blocked — the claim was already counted at poll time.
|
|
634
|
-
|
|
635
|
-
#### Task Expiry (task_timeout)
|
|
636
|
-
|
|
637
|
-
Set `task_timeout` (seconds) on a gig to give workers a deadline: once a task is claimed (queue gigs) or delivered (push gigs), the worker must submit a proof — or act on it (report/skip) — before the deadline. Default is `null`: tasks never expire.
|
|
638
|
-
|
|
639
|
-
- Expired tasks are blocked server-side: proof submission, skip, and report return `410 Gone`.
|
|
640
|
-
- Unclaimed queue items never expire — the clock starts at claim/delivery.
|
|
641
|
-
- Task listings (`GET /mailboxes/:mbxId/inbound`, dashboard inbound) include `expires_at` and `expired` per task.
|
|
642
|
-
- The owner resolves expired tasks with the endpoints below (also usable before expiry).
|
|
643
|
-
|
|
644
|
-
#### POST /gigs/:id/tasks/:msgId/extend (Owner Only)
|
|
645
|
-
|
|
646
|
-
Resets the task's expiry clock, flipping it back to not-expired in the worker's mailbox.
|
|
647
|
-
|
|
648
|
-
```json
|
|
649
|
-
// Response
|
|
650
|
-
{ "success": true, "expires_at": "2026-07-16T12:00:00.000Z", "expired": false }
|
|
651
|
-
```
|
|
652
|
-
|
|
653
|
-
#### POST /gigs/:id/tasks/:msgId/recycle (Owner Only)
|
|
654
|
-
|
|
655
|
-
Takes the task back from its current worker and redistributes it: queue gigs return it to the queue for the next worker (the previous holder won't receive it again); push gigs reassign it to another mailbox per the gig's distribution mode.
|
|
656
|
-
|
|
657
|
-
```json
|
|
658
|
-
// Response (queue gig)
|
|
659
|
-
{ "success": true, "requeued": true }
|
|
660
|
-
|
|
661
|
-
// Response (push gig)
|
|
662
|
-
{ "success": true, "reassigned_to": "01HX...", "reassigned_to_name": "Worker name" }
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
#### POST /gigs/:id/rotate-token (Owner Only)
|
|
666
|
-
|
|
667
|
-
```json
|
|
668
|
-
// Response
|
|
669
|
-
{
|
|
670
|
-
"email": "GIG_01HX..._newtoken.dollar-platoon@fwd.zoomgtm.com",
|
|
671
|
-
"webhook": "https://dollarplatoon.com/api/inbound/webhook/GIG_01HX...?token=newtoken"
|
|
672
|
-
}
|
|
673
|
-
```
|
|
674
|
-
|
|
675
|
-
Generates a new 6-char security token. Invalidates old email address and webhook URL. Old email lookup is deleted and replaced. Update all publisher integrations with the new URLs after rotating.
|
|
676
|
-
|
|
677
|
-
#### GET /gigs/:id/dashboard (Owner Only)
|
|
678
|
-
|
|
679
|
-
```json
|
|
680
|
-
// Response
|
|
681
|
-
{
|
|
682
|
-
"gig": { ... },
|
|
683
|
-
"mailboxes": [ ... ],
|
|
684
|
-
"proofs": [ ... ],
|
|
685
|
-
"rollups": [ ... ],
|
|
686
|
-
"inbound_messages": [ ... ]
|
|
687
|
-
}
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
Syncs on-chain balance on every load. Signs all S3 URLs for proof attachments.
|
|
691
|
-
|
|
692
|
-
#### POST /gigs/:id/deposit
|
|
693
|
-
|
|
694
|
-
```json
|
|
695
|
-
// Request
|
|
696
|
-
{ "wallet_alias_id": "alias_id", "amount": 100 }
|
|
697
|
-
|
|
698
|
-
// Response
|
|
699
|
-
{ "tx_hash": "0x...", "available_funds": 100 }
|
|
700
|
-
```
|
|
701
|
-
|
|
702
|
-
Deposits USDC from your hot wallet to the gig's on-chain balance. Remember to budget 110% of expected payouts to cover the platform fee.
|
|
703
|
-
|
|
704
|
-
### Mailboxes
|
|
705
|
-
|
|
706
|
-
| Method | Path | Auth | Description |
|
|
707
|
-
|--------|------|------|-------------|
|
|
708
|
-
| POST | `/gigs/:id/mailboxes` | Yes | Join gig (create mailbox) |
|
|
709
|
-
| GET | `/gigs/:id/mailboxes` | Yes | List mailboxes in gig (owner only) |
|
|
710
|
-
| PATCH | `/gigs/:id/mailboxes/:mbx_id` | Yes | Update mailbox (owner: priority/status; worker: tags) |
|
|
711
|
-
| DELETE | `/gigs/:id/mailboxes/:mbx_id` | Yes | Leave gig / remove mailbox |
|
|
712
|
-
| GET | `/mailboxes/mine` | Yes | List user's mailboxes across all gigs (`?tag=` substring filter) |
|
|
713
|
-
| GET | `/mailboxes/:mbxId/inbound` | Yes | Fetch inbound messages for mailbox |
|
|
714
|
-
| POST | `/gigs/:id/mailboxes/:mbxId/regenerate-token` | Yes | Regenerate share token |
|
|
715
|
-
|
|
716
|
-
#### POST /gigs/:id/mailboxes (Join Gig)
|
|
717
|
-
|
|
718
|
-
```json
|
|
719
|
-
// Request
|
|
720
|
-
{
|
|
721
|
-
"name": "John's Mailbox",
|
|
722
|
-
"email": "john@example.com",
|
|
723
|
-
"invite": "a1b2c3d4e5f6", // required for join_policy "invite" gigs — token from the invite link
|
|
724
|
-
"wallet_address": "0x...", // optional, auto-provisions hot wallet if omitted
|
|
725
|
-
"webhook": "https://...", // optional, for webhook task delivery
|
|
726
|
-
"notes": "I have experience with Reddit marketing",
|
|
727
|
-
"location": { "country": "US" },
|
|
728
|
-
"tags": ["urgent", "linkedin-batch"] // optional, free-form private labels (max 25 tags, 256 chars each)
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
// Response
|
|
732
|
-
{
|
|
733
|
-
"mailbox": {
|
|
734
|
-
"id": "01HX...",
|
|
735
|
-
"name": "John's Mailbox",
|
|
736
|
-
"gig_id": "GIG_01HX...",
|
|
737
|
-
"status": "active" // or "pending_approval" if gig.requires_approval
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
Validates reputation thresholds. Auto-creates wallet alias for external wallets. Gigs with `join_policy: "invite"` reject joins without a valid invite token (403); email-bound invites must match your account email and skip owner approval. Legacy gigs without a join_policy remain open joins.
|
|
179
|
+
## The shape of the whole thing
|
|
743
180
|
|
|
744
|
-
#### PATCH /gigs/:id/mailboxes/:mbx_id
|
|
745
|
-
|
|
746
|
-
```json
|
|
747
|
-
// Request (gig owner)
|
|
748
|
-
{ "priority": 5, "status": "active", "rate_limit_count": 5, "rate_limit_minutes": 60 }
|
|
749
|
-
|
|
750
|
-
// Request (mailbox worker)
|
|
751
|
-
{ "tags": ["urgent", "linkedin-batch"] }
|
|
752
|
-
|
|
753
|
-
// Response
|
|
754
|
-
{ "success": true, "status": "active", "tags": ["urgent", "linkedin-batch"] }
|
|
755
181
|
```
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
"tasks_received": 12, "proofs_submitted": 10, "response_rate": 0.83,
|
|
769
|
-
"tags": ["urgent", "linkedin-batch"]
|
|
770
|
-
}
|
|
771
|
-
]
|
|
772
|
-
}
|
|
182
|
+
Client Gigworker
|
|
183
|
+
│ │
|
|
184
|
+
├─ creates a gig, funds it with USDC │
|
|
185
|
+
├─ mints an invite link ──────────────────────▶│ joins, gets a mailbox
|
|
186
|
+
├─ sends tasks (webhook or email) │
|
|
187
|
+
│ │ │
|
|
188
|
+
│ └─ pushed to mailboxes ───────────────▶│ receives, or polls a queue
|
|
189
|
+
│ ├─ does the work
|
|
190
|
+
│◀──────────────────────────────────────────────┤ submits a proof
|
|
191
|
+
├─ approves (or the review timeout does) │
|
|
192
|
+
├─ triggers a rollup (or the daily cron does) │
|
|
193
|
+
└─ USDC pays out on Base ─────────────────────▶ │ paid_out_at is stamped
|
|
773
194
|
```
|
|
774
195
|
|
|
775
|
-
|
|
196
|
+
Every settled action writes an immutable event against a wallet, readable at
|
|
197
|
+
`GET /reputation/:wallet/events`. That ledger is the only signal this platform publishes — it does
|
|
198
|
+
not score or rate anyone. There is no dispute resolution, and no funds can be reversed.
|
|
776
199
|
|
|
777
|
-
|
|
200
|
+
An **order machine** runs the same picture backwards:
|
|
778
201
|
|
|
779
|
-
```json
|
|
780
|
-
// Response
|
|
781
|
-
{
|
|
782
|
-
"inbound_messages": [
|
|
783
|
-
{
|
|
784
|
-
"id": "...", "type": "email", "subject": "...", "from": "sender@example.com",
|
|
785
|
-
"payload": "...", "mailbox_id": "...", "forwarded_at": "...",
|
|
786
|
-
"attachments": [{ "filename": "...", "content_type": "...", "url": "https://..." }]
|
|
787
|
-
}
|
|
788
|
-
]
|
|
789
|
-
}
|
|
790
202
|
```
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
```json
|
|
805
|
-
// Request
|
|
806
|
-
{
|
|
807
|
-
"mailbox_id": "01HX...",
|
|
808
|
-
"task_identifier": "reddit-thread-abc123",
|
|
809
|
-
"proofs": ["https://reddit.com/r/...", "https://s3.amazonaws.com/..."]
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// Response
|
|
813
|
-
{
|
|
814
|
-
"proof": {
|
|
815
|
-
"id": "01HX...",
|
|
816
|
-
"status": "pending",
|
|
817
|
-
"timeout_at": "2026-02-18T..."
|
|
818
|
-
},
|
|
819
|
-
"warning": "Warning: gig available funds are less than the task price"
|
|
820
|
-
}
|
|
203
|
+
Participant (buys) Vendor (owns the machine, does the work)
|
|
204
|
+
│ │
|
|
205
|
+
├─ joins by invite, gets a mailbox │
|
|
206
|
+
├─ saves a draft order through the webhook │
|
|
207
|
+
├─ publishes it WITH a USDC deposit ──────────▶ │ receives it in their own mailbox
|
|
208
|
+
│ (the deposit and the send are one call)├─ does the work
|
|
209
|
+
│◀──────────────────────────────────────────────┤ delivers a proof, deliverable withheld
|
|
210
|
+
├─ reads the evidence │
|
|
211
|
+
├─ may UNDO and take the deposit back ──────────┤ …and so may the vendor, until here
|
|
212
|
+
├─ approves (or the review timeout does) ◀── the point of no return
|
|
213
|
+
├─ either party triggers the rollup │
|
|
214
|
+
└─ USDC pays out on Base ─────────────────────▶ │ paid_out_at is stamped
|
|
215
|
+
└─ private_note is released to the buyer
|
|
821
216
|
```
|
|
822
|
-
|
|
823
|
-
**`task_identifier` is critical.** This field links a proof to the specific task it fulfills.
|
|
824
|
-
- For **`queue` gigs**, pass the polled task's `id` (the inbound message ULID returned by `/queue/poll`). The server uses this to atomically claim the queue item out of the queue to your mailbox.
|
|
825
|
-
- For **`inbound_proof` gigs** and other distribution modes, use the task's unique reference (URL, ticket ID, publisher-supplied `task_id`, etc.).
|
|
826
|
-
- **Avoid using the subject line** — subjects are rarely unique, and collisions cause duplicate-submission 409s.
|
|
827
|
-
|
|
828
|
-
The `warning` field appears when the gig's `available_funds` is less than the task price. The proof is still accepted, but payout will fail until the client deposits more funds.
|
|
829
|
-
|
|
830
|
-
Price is locked at submission time (`locked_price`).
|
|
831
|
-
|
|
832
|
-
#### PATCH /gigs/:id/proofs/:proof_id (Review)
|
|
833
|
-
|
|
834
|
-
```json
|
|
835
|
-
// Request (approve)
|
|
836
|
-
{ "action": "approve", "feedback": "Great work!" }
|
|
837
|
-
|
|
838
|
-
// Request (reject)
|
|
839
|
-
{ "action": "reject", "feedback": "Screenshot doesn't match", "rejection_tag": "incomplete" }
|
|
840
|
-
|
|
841
|
-
// Response
|
|
842
|
-
{ "success": true, "status": "approved" }
|
|
843
|
-
```
|
|
844
|
-
|
|
845
|
-
Rejection tags (required when rejecting): `low_quality`, `incomplete`, `fake_proof`, `duplicate`, `unresponsive`, `other`
|
|
846
|
-
|
|
847
|
-
Rejection weights (reputation impact): fake_proof=5x, duplicate=3x, incomplete=2x, unresponsive=2x, low_quality=1x, other=1x
|
|
848
|
-
|
|
849
|
-
#### POST /gigs/:id/proofs/:proof_id/report (Owner Only)
|
|
850
|
-
|
|
851
|
-
```json
|
|
852
|
-
// Response
|
|
853
|
-
{ "success": true, "status": "reported" }
|
|
854
|
-
```
|
|
855
|
-
|
|
856
|
-
Only works on `timeout_approved` proofs. Reported proofs are excluded from rollups and will not be paid.
|
|
857
|
-
|
|
858
|
-
### Rollups (Payouts)
|
|
859
|
-
|
|
860
|
-
| Method | Path | Auth | Description |
|
|
861
|
-
|--------|------|------|-------------|
|
|
862
|
-
| GET | `/gigs/:id/rollups` | Yes | List rollups for gig |
|
|
863
|
-
| POST | `/gigs/:id/rollups` | Yes | Trigger manual rollup (owner only) |
|
|
864
|
-
| GET | `/rollups/mine` | Yes | List rollups across user's mailboxes |
|
|
865
|
-
|
|
866
|
-
#### POST /gigs/:id/rollups (Trigger Payout)
|
|
867
|
-
|
|
868
|
-
```json
|
|
869
|
-
// Response
|
|
870
|
-
{
|
|
871
|
-
"rollups": [
|
|
872
|
-
{
|
|
873
|
-
"id": "...",
|
|
874
|
-
"mailbox_id": "...",
|
|
875
|
-
"wallet_address": "0x...",
|
|
876
|
-
"proof_ids": ["...", "..."],
|
|
877
|
-
"gross_amount": 5.00,
|
|
878
|
-
"platform_fee": 0.50,
|
|
879
|
-
"net_amount": 5.00,
|
|
880
|
-
"tx_hash": "0x...",
|
|
881
|
-
"status": "paid"
|
|
882
|
-
}
|
|
883
|
-
],
|
|
884
|
-
"available_funds": 44.50,
|
|
885
|
-
"skipped_below_minimum": [
|
|
886
|
-
{ "mailbox_id": "...", "amount": 0.50 }
|
|
887
|
-
]
|
|
888
|
-
}
|
|
889
|
-
```
|
|
890
|
-
|
|
891
|
-
Groups approved + timeout_approved proofs by mailbox. Pre-checks `available_funds >= gross_amount + platform_fee` (no debt allowed). Worker receives full `gross_amount`. Skips mailboxes below `min_payout` threshold.
|
|
892
|
-
|
|
893
|
-
**Will return 400 error if the gig cannot cover the total cost (gross + 10% fee).**
|
|
894
|
-
|
|
895
|
-
### Inbound (Task Distribution)
|
|
896
|
-
|
|
897
|
-
| Method | Path | Auth | Description |
|
|
898
|
-
|--------|------|------|-------------|
|
|
899
|
-
| POST | `/inbound/email` | No | Resend inbound email webhook |
|
|
900
|
-
| POST | `/inbound/webhook/:gig_id` | No | Publisher webhook task delivery |
|
|
901
|
-
|
|
902
|
-
#### POST /inbound/webhook/:gig_id?token=...
|
|
903
|
-
|
|
904
|
-
**This is the preferred endpoint for AI agents and publisher apps to deliver tasks.** Accepts **JSON** (default) or **HTML/plain text** payloads. Content-Type header determines parsing.
|
|
905
|
-
|
|
906
|
-
**For AI agents:** Use `Content-Type: text/html` with the dual-format HTML pattern (see "Dual-Format HTML" section above) to deliver tasks that work for both human gigworkers and AI agents. Include a hidden `div.agent-data` with `data-agent-json` for structured data extraction.
|
|
907
|
-
|
|
908
|
-
**JSON payload (Content-Type: application/json):**
|
|
909
|
-
|
|
910
|
-
```json
|
|
911
|
-
// Request
|
|
912
|
-
{ "task": "Comment on this Reddit thread", "url": "https://..." }
|
|
913
|
-
|
|
914
|
-
// Response
|
|
915
|
-
{ "status": "forwarded", "targets": 3 }
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
**HTML payload (Content-Type: text/html or text/plain) — recommended for mixed human+agent gigs:**
|
|
919
|
-
|
|
920
|
-
```bash
|
|
921
|
-
curl -X POST "https://dollarplatoon.com/api/inbound/webhook/GIG_01HX...?token=abc123&subject=My+Report" \
|
|
922
|
-
-H "Content-Type: text/html" \
|
|
923
|
-
-d '<h1>Task Details</h1><p>Please complete this task...</p>'
|
|
924
|
-
```
|
|
925
|
-
|
|
926
|
-
```json
|
|
927
|
-
// Response
|
|
928
|
-
{ "status": "forwarded", "targets": 3 }
|
|
929
|
-
```
|
|
930
|
-
|
|
931
|
-
When HTML/text is sent, the message is stored with `type: "email"` and rendered as formatted HTML on the frontend (same as email-sourced tasks). An optional `subject` query parameter can be included to set the message subject line.
|
|
932
|
-
|
|
933
|
-
Requires valid `token` query parameter matching the gig's security token. Returns 403 if token is invalid. Selects mailboxes via distribution algorithm, forwards payload to each mailbox webhook.
|
|
934
|
-
|
|
935
|
-
**Distribution Modes:**
|
|
936
|
-
|
|
937
|
-
- **round_robin** — Cursor-based fair rotation through active mailboxes
|
|
938
|
-
- **random** — Uniform random selection
|
|
939
|
-
- **priority_weighted** — Weighted by mailbox priority (1-10, higher = more tasks)
|
|
940
|
-
- **free_for_all** — All active mailboxes receive the task
|
|
941
|
-
- **queue** — Tasks stored in a shared queue; workers poll and claim tasks on-demand
|
|
942
|
-
- **inbound_proof** — No tasks distributed; workers submit proofs directly without task assignment
|
|
943
|
-
|
|
944
|
-
### Queue (FIFO)
|
|
945
|
-
|
|
946
|
-
| Method | Path | Auth | Description |
|
|
947
|
-
|--------|------|------|-------------|
|
|
948
|
-
| POST | `/gigs/:id/queue/poll` | Yes | Poll for available tasks (gigworker, queue gigs only) |
|
|
949
|
-
| POST | `/gigs/:id/queue/:msgId/decline` | Yes | Skip a task so future polls don't return it to you (per-worker, does not hide from other workers) |
|
|
950
|
-
| GET | `/gigs/:id/queue` | Yes | List queued tasks (owner sees `declined_count` per item) |
|
|
951
|
-
| DELETE | `/gigs/:id/tasks/:taskId` | Yes | Delete a stored task/inbound message (gig owner only) |
|
|
952
|
-
|
|
953
|
-
#### POST /gigs/:id/queue/poll
|
|
954
|
-
|
|
955
|
-
```json
|
|
956
|
-
// Request
|
|
957
|
-
{ "count": 2 } // optional, default 2, max 20
|
|
958
|
-
|
|
959
|
-
// Response
|
|
960
|
-
{
|
|
961
|
-
"tasks": [
|
|
962
|
-
{
|
|
963
|
-
"id": "...", "type": "webhook", "subject": "...",
|
|
964
|
-
"payload": "...", "forwarded_at": "..."
|
|
965
|
-
}
|
|
966
|
-
],
|
|
967
|
-
"count": 1,
|
|
968
|
-
"rate_limit": { "count": 5, "minutes": 60, "source": "gig", "used": 3, "remaining": 2, "retry_at": null } // null if no limit configured
|
|
969
|
-
}
|
|
970
|
-
```
|
|
971
|
-
|
|
972
|
-
For `queue` gigs only. Returns unclaimed queued tasks in the configured queue order, skipping items you've already submitted a proof for or declined. Tasks are not forwarded to mailboxes — gigworkers must poll to claim them.
|
|
973
|
-
|
|
974
|
-
If the gig (or your mailbox specifically) has a worker rate limit, polling past it returns `429` with an `error` message stating the limit and how long to wait, plus the same `rate_limit` object with `retry_at` set. Claims are capped to your remaining allowance — e.g. requesting 10 tasks with 2 remaining returns at most 2.
|
|
975
|
-
|
|
976
|
-
#### POST /gigs/:id/queue/:msgId/decline
|
|
977
|
-
|
|
978
|
-
Marks a queue item as skipped *for the calling worker only*. Idempotent. Returns `{"success": true}`.
|
|
979
|
-
|
|
980
|
-
Use this when a polled task isn't suitable for you (spam, duplicate, ineligible, etc.) so future polls return fresh items instead of the same ones at the head of the FIFO queue. Other workers still see the item. The gig owner sees a `declined_count` on their dashboard so they can prune genuinely unworkable items.
|
|
981
|
-
|
|
982
|
-
**For Gigworkers (Queue gigs):**
|
|
983
|
-
|
|
984
|
-
- Tasks are NOT forwarded to your mailbox. Instead, use "Poll New Tasks" in the UI or call `POST /gigs/:id/queue/poll` to claim tasks from the shared queue.
|
|
985
|
-
- Tasks are returned in the configured queue order (FIFO or LIFO) and filtered against proofs you've already submitted or items you've declined.
|
|
986
|
-
- After polling, submit proofs via `POST /gigs/:id/proofs` using the polled task's `id` as `task_identifier` — this atomically claims the queue item into your mailbox.
|
|
987
|
-
- If a task isn't suitable, call `POST /gigs/:id/queue/:msgId/decline` to skip it. Declining is free and doesn't affect other workers.
|
|
988
|
-
|
|
989
|
-
### Public (No Auth Required)
|
|
990
|
-
|
|
991
|
-
| Method | Path | Auth | Description |
|
|
992
|
-
|--------|------|------|-------------|
|
|
993
|
-
| GET | `/public/mailbox-info?token=...` | No | Get mailbox info via share token |
|
|
994
|
-
| POST | `/public/upload-presign` | No | Get S3 presigned upload URL |
|
|
995
|
-
| POST | `/public/submit-proof` | No | Submit proof via public share link |
|
|
996
|
-
| GET | `/public/read-url?key=...&token=...` | No | Get presigned S3 read URL |
|
|
997
|
-
|
|
998
|
-
Rate limited: 10-30 requests/min per share token.
|
|
999
|
-
|
|
1000
|
-
#### POST /public/submit-proof
|
|
1001
|
-
|
|
1002
|
-
```json
|
|
1003
|
-
// Request
|
|
1004
|
-
{
|
|
1005
|
-
"share_token": "tok_...",
|
|
1006
|
-
"task_identifier": "reddit-thread-abc123",
|
|
1007
|
-
"proofs": ["https://..."]
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Response
|
|
1011
|
-
{ "proof_id": "...", "status": "pending" }
|
|
1012
|
-
```
|
|
1013
|
-
|
|
1014
|
-
### Reviews
|
|
1015
|
-
|
|
1016
|
-
| Method | Path | Auth | Description |
|
|
1017
|
-
|--------|------|------|-------------|
|
|
1018
|
-
| POST | `/gigs/:id/reviews` | Yes | Leave star review (1-5) |
|
|
1019
|
-
| PATCH | `/reviews/:id/resolve` | Yes | Mark review as resolved (reviewer only) |
|
|
1020
|
-
| GET | `/reputation/:wallet/reviews` | No | List reviews for wallet |
|
|
1021
|
-
|
|
1022
|
-
#### POST /gigs/:id/reviews
|
|
1023
|
-
|
|
1024
|
-
```json
|
|
1025
|
-
// Request
|
|
1026
|
-
{ "target_wallet": "0x...", "stars": 4, "comment": "Reliable worker, good quality" }
|
|
1027
|
-
|
|
1028
|
-
// Response
|
|
1029
|
-
{ "review": { "id": "...", "stars": 4 } }
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
One review per reviewer-target pair per gig. Reviewer role auto-detected (client if owner, gigworker otherwise).
|
|
1033
|
-
|
|
1034
|
-
### Reputation
|
|
1035
|
-
|
|
1036
|
-
| Method | Path | Auth | Description |
|
|
1037
|
-
|--------|------|------|-------------|
|
|
1038
|
-
| GET | `/reputation/:wallet` | No | Get computed reputation score |
|
|
1039
|
-
| GET | `/reputation/alias/:alias_id` | No | Get reputation by wallet alias |
|
|
1040
|
-
| GET | `/reputation/:wallet/events` | No | List raw reputation events |
|
|
1041
|
-
|
|
1042
|
-
#### GET /reputation/:wallet
|
|
1043
|
-
|
|
1044
|
-
```json
|
|
1045
|
-
// Response
|
|
1046
|
-
{
|
|
1047
|
-
"wallet": "0x...",
|
|
1048
|
-
"volume": 150.50,
|
|
1049
|
-
"quality": 0.92,
|
|
1050
|
-
"recency": 0.85,
|
|
1051
|
-
"social": 4.2,
|
|
1052
|
-
"event_count": 47
|
|
1053
|
-
}
|
|
1054
|
-
```
|
|
1055
|
-
|
|
1056
|
-
### Wallets
|
|
1057
|
-
|
|
1058
|
-
| Method | Path | Auth | Description |
|
|
1059
|
-
|--------|------|------|-------------|
|
|
1060
|
-
| POST | `/wallets` | Yes | Create wallet alias |
|
|
1061
|
-
| GET | `/wallets` | Yes | List user's wallet aliases |
|
|
1062
|
-
| GET | `/wallets/:alias_id` | Yes | Get wallet detail |
|
|
1063
|
-
| GET | `/wallets/:alias_id/balances` | Yes | Get on-chain balances (ETH + USDC) |
|
|
1064
|
-
| POST | `/wallets/:alias_id/transfer` | Yes | Transfer USDC from hot wallet |
|
|
1065
|
-
| DELETE | `/wallets/:alias_id` | Yes | Delete wallet alias |
|
|
1066
|
-
|
|
1067
|
-
#### POST /wallets
|
|
1068
|
-
|
|
1069
|
-
```json
|
|
1070
|
-
// Request (hot wallet — platform-managed)
|
|
1071
|
-
{ "label": "My Hot Wallet", "is_hot_wallet": true }
|
|
1072
|
-
|
|
1073
|
-
// Request (external wallet — self-custody)
|
|
1074
|
-
{ "label": "My MetaMask", "is_hot_wallet": false, "evm_address": "0x..." }
|
|
1075
|
-
|
|
1076
|
-
// Response
|
|
1077
|
-
{ "wallet": { "alias_id": "...", "label": "My Hot Wallet", "is_hot_wallet": true, "created_at": "..." } }
|
|
1078
|
-
```
|
|
1079
|
-
|
|
1080
|
-
One hot wallet per user. External wallets are unlimited.
|
|
1081
|
-
|
|
1082
|
-
#### GET /wallets/:alias_id/balances
|
|
1083
|
-
|
|
1084
|
-
```json
|
|
1085
|
-
// Response
|
|
1086
|
-
{ "evm_address": "0x...", "eth_balance": "0.05", "usdc_balance": "100.000000" }
|
|
1087
|
-
```
|
|
1088
|
-
|
|
1089
|
-
#### POST /wallets/:alias_id/transfer
|
|
1090
|
-
|
|
1091
|
-
```json
|
|
1092
|
-
// Request
|
|
1093
|
-
{ "to_address": "0x...", "amount": 50 }
|
|
1094
|
-
|
|
1095
|
-
// Response
|
|
1096
|
-
{ "tx_hash": "0x..." }
|
|
1097
|
-
```
|
|
1098
|
-
|
|
1099
|
-
Hot wallets only.
|
|
1100
|
-
|
|
1101
|
-
### Profiles
|
|
1102
|
-
|
|
1103
|
-
| Method | Path | Auth | Description |
|
|
1104
|
-
|--------|------|------|-------------|
|
|
1105
|
-
| PATCH | `/profiles/me` | Yes | Update own profile |
|
|
1106
|
-
| GET | `/profiles/:identifier` | No | Get public profile (by email or alias_id) |
|
|
1107
|
-
| GET | `/profiles/:identifier/private` | Yes | Get private profile (requires shared gig relationship) |
|
|
1108
|
-
|
|
1109
|
-
#### PATCH /profiles/me
|
|
1110
|
-
|
|
1111
|
-
```json
|
|
1112
|
-
// Request
|
|
1113
|
-
{ "display_name": "John Doe", "bio": "Experienced social media marketer", "avatar_url": "https://..." }
|
|
1114
|
-
```
|
|
1115
|
-
|
|
1116
|
-
### Upload
|
|
1117
|
-
|
|
1118
|
-
| Method | Path | Auth | Description |
|
|
1119
|
-
|--------|------|------|-------------|
|
|
1120
|
-
| POST | `/upload/presign` | Yes | Get presigned S3 upload URL |
|
|
1121
|
-
|
|
1122
|
-
```json
|
|
1123
|
-
// Request
|
|
1124
|
-
{ "filename": "screenshot.png", "content_type": "image/png", "prefix": "proofs" }
|
|
1125
|
-
|
|
1126
|
-
// Response
|
|
1127
|
-
{ "presigned_url": "https://s3...", "url": "https://s3...", "key": "proofs/...", "bucket": "..." }
|
|
1128
|
-
```
|
|
1129
|
-
|
|
1130
|
-
Prefix options: `"avatars"`, `"gig-icons"`, or `"proofs"` (default). Presigned URL expires in 1 hour.
|
|
1131
|
-
|
|
1132
|
-
### OfficeX Integration
|
|
1133
|
-
|
|
1134
|
-
| Method | Path | Auth | Description |
|
|
1135
|
-
|--------|------|------|-------------|
|
|
1136
|
-
| POST | `/officex/webhook` | No | Handle OfficeX install/uninstall |
|
|
1137
|
-
| POST | `/officex/login` | No | Login via OfficeX credentials |
|
|
1138
|
-
|
|
1139
|
-
#### POST /officex/webhook
|
|
1140
|
-
|
|
1141
|
-
```json
|
|
1142
|
-
// Request
|
|
1143
|
-
{ "event": "INSTALL", "payload": { "install_id": "...", "install_secret": "...", "user_id": "...", "app_id": "..." } }
|
|
1144
|
-
|
|
1145
|
-
// Response
|
|
1146
|
-
{ "agent_context": { "user_email": "officex-...@dollar-platoon.local", "api_key": "...", "api_url": "https://...", "install_id": "...", "install_secret": "..." } }
|
|
1147
|
-
```
|
|
1148
|
-
|
|
1149
|
-
Creates user with email `officex-{user_id}@dollar-platoon.local`. Auto-provisions hot wallet.
|
|
1150
|
-
|
|
1151
|
-
#### POST /officex/login
|
|
1152
|
-
|
|
1153
|
-
```json
|
|
1154
|
-
// Request
|
|
1155
|
-
{ "officex_user_id": "...", "officex_install_id": "..." }
|
|
1156
|
-
|
|
1157
|
-
// Response
|
|
1158
|
-
{ "email": "officex-...@dollar-platoon.local", "api_key": "..." }
|
|
1159
|
-
```
|
|
1160
|
-
|
|
1161
|
-
Returns 404 if user not found (webhook may not have fired yet). Returns 403 if install_id mismatch.
|
|
1162
|
-
|
|
1163
|
-
### Admin
|
|
1164
|
-
|
|
1165
|
-
| Method | Path | Auth | Description |
|
|
1166
|
-
|--------|------|------|-------------|
|
|
1167
|
-
| POST | `/admin/users/provision` | `x-admin-key` header | Programmatically provision (or fetch) an account |
|
|
1168
|
-
|
|
1169
|
-
#### POST /admin/users/provision
|
|
1170
|
-
|
|
1171
|
-
Idempotent. Creates the account (and auto-provisions a hot wallet) if the email is new — `201` with `"created": true`. If the account already exists, no changes are made and the existing account info is returned — `200` with `"created": false`. The API key is never rotated by this endpoint.
|
|
1172
|
-
|
|
1173
|
-
```json
|
|
1174
|
-
// Request (header: x-admin-key: <ADMIN_API_KEY>)
|
|
1175
|
-
{ "email": "user@example.com" }
|
|
1176
|
-
|
|
1177
|
-
// Response — 201 if newly created, 200 if the account already existed
|
|
1178
|
-
{
|
|
1179
|
-
"created": false,
|
|
1180
|
-
"account": {
|
|
1181
|
-
"email": "user@example.com",
|
|
1182
|
-
"api_key": "base64url_encoded_key",
|
|
1183
|
-
"display_name": null,
|
|
1184
|
-
"created_at": "2026-02-14T...",
|
|
1185
|
-
"officex_user_id": null,
|
|
1186
|
-
"officex_install_id": null
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
```
|
|
1190
|
-
|
|
1191
|
-
Returns 503 if `ADMIN_API_KEY` is not configured, 401 if the header is missing, 403 if the key is invalid.
|
|
1192
|
-
|
|
1193
|
-
### Health
|
|
1194
|
-
|
|
1195
|
-
| Method | Path | Auth | Description |
|
|
1196
|
-
|--------|------|------|-------------|
|
|
1197
|
-
| GET | `/health` | No | Health check |
|
|
1198
|
-
|
|
1199
|
-
```json
|
|
1200
|
-
{ "status": "ok", "stage": "production", "timestamp": "2026-02-14T..." }
|
|
1201
|
-
```
|
|
1202
|
-
|
|
1203
|
-
---
|
|
1204
|
-
|
|
1205
|
-
## Proof Lifecycle
|
|
1206
|
-
|
|
1207
|
-
```
|
|
1208
|
-
submitted (locked_price snapshot, timeout_at set)
|
|
1209
|
-
→ approved (client action) → rolled up → payout on-chain → paid
|
|
1210
|
-
→ rejected (requires rejection_tag + optional feedback)
|
|
1211
|
-
→ timeout_approved (daily cron, after review_timeout) → same rollup path
|
|
1212
|
-
→ reported (post-timeout flag by owner, excluded from payouts)
|
|
1213
|
-
```
|
|
1214
|
-
|
|
1215
|
-
Rejection tags: `low_quality`, `incomplete`, `fake_proof`, `duplicate`, `unresponsive`, `other`
|
|
1216
|
-
|
|
1217
|
-
---
|
|
1218
|
-
|
|
1219
|
-
## Rollup & Payout Flow
|
|
1220
|
-
|
|
1221
|
-
1. Client triggers `POST /gigs/:id/rollups` (or daily cron runs automatically)
|
|
1222
|
-
2. Groups approved proofs by mailbox, sums `locked_price` per mailbox
|
|
1223
|
-
3. Skips mailboxes below `min_payout` threshold
|
|
1224
|
-
4. Pre-checks: `gross_amount + platform_fee <= available_funds` — **fails with 400 if underfunded**
|
|
1225
|
-
5. Calls on-chain `payout(gig_id, wallet, gross_amount, rollup_id)`
|
|
1226
|
-
6. On success: stores `tx_hash`, status → `paid`, creates reputation event
|
|
1227
|
-
7. On failure: status → `failed`, retried by next daily cron run
|