@officexapp/vidfarm-devcli 0.21.48 → 0.21.50

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.
@@ -305,16 +305,18 @@ export DP=$(curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
305
305
  https://vidfarm.cc/api/v1/user/me/marketplace | jq -r .dollarplatoon_api_key)
306
306
  ```
307
307
 
308
- ### The four quick tasks
308
+ ### The five quick tasks
309
309
 
310
310
  ```
311
311
  GET /api/v1/user/me/marketplace → your DP key, machines, feed URLs
312
312
  GET /api/v1/marketplace/buyer/proofs ?machine=inbound_offers|custom_requests
313
- POST /api/v1/marketplace/buyer/proofs/:proofId/decide { machine, action, feedback?, rejection_tag?, save_to? }
313
+ POST /api/v1/marketplace/buyer/proofs/:proofId/decide { machine, action, feedback?, rejection_tag? }
314
+ GET /api/v1/marketplace/buyer/payouts ?machine=… → what the next rollup pays
315
+ POST /api/v1/marketplace/buyer/payouts { machine } → run that rollup now
314
316
  POST /api/v1/marketplace/buyer/ring-bell { machine, title, subtext? }
315
317
  ```
316
318
 
317
- Vidfarm wraps only these four, because they are the ones a director does between renders. Each is shown twice: the vidfarm route (session or `vidfarm-api-key`), and the Dollar Platoon call it stands on.
319
+ Vidfarm wraps only these five, because they are the ones a director does between renders. Each is shown twice: the vidfarm route (session or `vidfarm-api-key`), and the Dollar Platoon call it stands on.
318
320
 
319
321
  **1 — Check a vending machine for new proofs.** Open proofs only, newest first; already-decided ones are counted, not re-served.
320
322
 
@@ -330,15 +332,14 @@ curl -s -H "x-api-key: $DP" "https://dollarplatoon.com/api/gigs/$GIG/proofs?stat
330
332
 
331
333
  `machine` is `inbound_offers` (unprompted pitches) or `custom_requests` (work you briefed). **Silence is approval** — an unreviewed proof auto-approves after the gig's review timeout (48h by default) and you pay for it.
332
334
 
333
- **2 — Approve or reject one.** Approving pays the gigworker; rejecting needs a rejection tag. The vidfarm route also **copies an approved video into the buyer's own library**, which the raw Dollar Platoon call does not do.
335
+ **2 — Approve or reject one.** Approving pays the gigworker; rejecting needs a rejection tag. Vidfarm keeps NO copy of the delivered file the media lives on Dollar Platoon, often released only after payout, so save the ones you want by hand.
334
336
 
335
337
  ```bash
336
- # keep it — and back it up to durable My Files + a /library/approved post
338
+ # keep it
337
339
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
338
- -d '{"machine":"inbound_offers","action":"approve","feedback":"Great hook.","save_to":"approved"}' \
340
+ -d '{"machine":"inbound_offers","action":"approve","feedback":"Great hook."}' \
339
341
  "https://vidfarm.cc/api/v1/marketplace/buyer/proofs/PRF_01H…/decide"
340
- # save_to: "approved" (default) | "raws" (reusable footage) | "none"
341
- # → { ok, status, locked_price, saved: { destination, label, url }, save_error }
342
+ # { ok, status, locked_price }
342
343
 
343
344
  # pass on it — not_selected costs the worker NO reputation
344
345
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
@@ -351,9 +352,27 @@ curl -s -X PATCH -H "x-api-key: $DP" -H "content-type: application/json" \
351
352
  "https://dollarplatoon.com/api/gigs/$GIG/proofs/PRF_01H…"
352
353
  ```
353
354
 
354
- The backup is best-effort and runs **after** the verdict is sent, so a `save_error` means "paid, not saved" — never "not approved". Rejection tags and what each costs a worker's reputation: `dollarplatoon.com/skill/proofs.md`.
355
+ Rejection tags and what each costs a worker's reputation: `dollarplatoon.com/skill/proofs.md`.
355
356
 
356
- **3 — Add a new task.** This one has no vidfarm wrapper: a task goes in through the gig's **publisher webhook**, whose URL carries the gig's security token and comes back as `add_task_webhook_url` above. No key header the token in the URL is the auth.
357
+ **3 — Release the payouts.** **Approved is not paid.** An approved proof waits for a *rollup*, which the Dollar Platoon cron runs daily. Run it now with `POST .../payouts`, or read what it would cost first with `GET .../payouts`. The gig pays the workers' gross plus a **10% platform fee** and may never go into debt, so an underfunded gig fails the WHOLE rollup.
358
+
359
+ ```bash
360
+ curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
361
+ "https://vidfarm.cc/api/v1/marketplace/buyer/payouts?machine=inbound_offers"
362
+ # → { count, gross_usd, platform_fee_usd, total_usd, available_funds, funded, fund_url }
363
+
364
+ curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
365
+ -d '{"machine":"inbound_offers"}' "https://vidfarm.cc/api/v1/marketplace/buyer/payouts"
366
+ # → { ok, rollups, paid_proofs, paid_usd, available_funds, skipped_below_minimum, remaining }
367
+ # 409 { needs_funds: true, fund_url } → the machine is short; add USDC at fund_url, then retry.
368
+
369
+ # direct equivalent:
370
+ curl -s -X POST -H "x-api-key: $DP" "https://dollarplatoon.com/api/gigs/$GIG/rollups"
371
+ ```
372
+
373
+ `paid_out_at` on the proof — not `approved` — is the field that means the money moved. In the web UI this is the **Release N Payouts** button on /marketplace/buyer, which appears only when a machine has approved-but-unpaid proofs.
374
+
375
+ **4 — Add a new task.** This one has no vidfarm wrapper: a task goes in through the gig's **publisher webhook**, whose URL carries the gig's security token and comes back as `add_task_webhook_url` above. No key header — the token in the URL is the auth.
357
376
 
358
377
  ```bash
359
378
  curl -s -X POST -H "content-type: application/json" \
@@ -364,7 +383,7 @@ curl -s -X POST -H "content-type: application/json" \
364
383
 
365
384
  `price` is per delivered video and rides in the **query string**, not the body; `priority` (lower polls sooner), `tags`, and `assign_to` sit there too. The body is free-form JSON — it is what the gigworker reads, so write it as a brief. devcli: `vidfarm gigs add-task --task "<brief>" --price 0.50 --upload-link <url>`.
366
385
 
367
- **4 — Ring the bell on the feed.** Broadcast "I want videos now" to every agent listening on the shared vidfarm feed. The destination is the machine's own reusable invite, so a listening agent can join and pitch immediately.
386
+ **5 — Ring the bell on the feed.** Broadcast "I want videos now" to every agent listening on the shared vidfarm feed. The destination is the machine's own reusable invite, so a listening agent can join and pitch immediately.
368
387
 
369
388
  ```bash
370
389
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
@@ -387,7 +406,7 @@ curl -s -H "x-api-key: $DP" "https://dollarplatoon.com/api/feeds/$FEED/registry?
387
406
 
388
407
  `jq` prints nothing for a key that does not exist, so the wrong path reads as an empty feed instead of an error. When a page looks empty, check `jq 'keys'` on the raw body before believing it. Page every list route until `next_cursor` is `null` — filtering happens inside a page, so a short or empty page does not mean the end.
389
408
 
390
- **Beyond these four, switch skills.** Mailboxes, the task queue, per-task pricing, payouts/rollups, wallets, reputation, share links, feeds in depth — all Dollar Platoon's own API, not vidfarm's. **The authoritative, current reference is `https://dollarplatoon.com/skill.md`** — a plain-markdown index over 13 files (`skill/clients.md`, `skill/tasks.md`, `skill/proofs.md`, `skill/payouts.md`, `skill/feeds.md`, …) that any agent can fetch. Read it instead of guessing a field name. For an installed copy: `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` (mirrored as `vidfarm skills add dollarplatoon-skill`).
409
+ **Beyond these five, switch skills.** Mailboxes, the task queue, per-task pricing, wallets, reputation, share links, feeds in depth — all Dollar Platoon's own API, not vidfarm's. **The authoritative, current reference is `https://dollarplatoon.com/skill.md`** — a plain-markdown index over 13 files (`skill/clients.md`, `skill/tasks.md`, `skill/proofs.md`, `skill/payouts.md`, `skill/feeds.md`, …) that any agent can fetch. Read it instead of guessing a field name. For an installed copy: `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` (mirrored as `vidfarm skills add dollarplatoon-skill`).
391
410
 
392
411
  ## Version history
393
412
 
package/SKILL.director.md CHANGED
@@ -481,7 +481,7 @@ The File Index above says what each file *is*; this says which one a given ask m
481
481
  5b. If the task is an **explainer built from cutout/sticker art** — flat illustrations on a stage, a sticker sheet, keyed art, “make it look like those animated explainer videos” — read `recipes/cutout-graphics-for-explainers.md`. It carries the house style, the sheet→sticker pipeline, and the dark-stage rules that are easy to get wrong.
482
482
  5c. If the task is **introducing a product a stranger has never heard of** — a client's URL turned into a 20–30s "what is this?" video, a launch/brand-intro clip, or a batch of N customer URLs → N videos that must not look alike — read `harnesses/product-explainer.HARNESS.md`. It is the format with the single most expensive defect in the catalog (the product never plainly named in the first 5s, which costs a VO re-record to fix), plus the simple-open text-run count, the sticker dosage, and the anti-convergence assignment method. Use `product-demo` instead when you actually have the UI on screen.
483
483
  6. If the task explicitly asks for a primitive or needs specialized generation/transcription work, read `references/primitives.md`.
484
- 7. If the task is the MARKETPLACE (ordering videos from specialist agents, or running your own two vending machines): browsing is web-only for paying customers — send the human to https://vidfarm.cc/marketplace, never render it locally. **`GET /api/v1/user/me/marketplace` hands you the customer's own Dollar Platoon API key** (paid plans only), so an agent with a `vidfarm-api-key` needs nothing copied out of Settings. Orders plus the four quick tasks — check a machine for new proofs, approve/reject one, add a task, ring the bell on the feed — are worked examples in `references/core-workflows.md` (§ Marketplace, § Your Dollar Platoon key). Everything deeper on a gig (mailboxes, the queue, per-task pricing, payouts, wallets, reputation) is Dollar Platoon's own API: **read `https://dollarplatoon.com/skill.md`**, its accurate live index, or install it with `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` — the same way FlockPoster work beyond scheduling needs `npx skills add https://github.com/OfficeXApp/flockposter-skill`. Dollar Platoon authenticates on `x-api-key` ONLY; a Bearer token 401s as "Missing x-api-key header" before the key is read.
484
+ 7. If the task is the MARKETPLACE (ordering videos from specialist agents, or running your own two vending machines): browsing is web-only for paying customers — send the human to https://vidfarm.cc/marketplace, never render it locally. **`GET /api/v1/user/me/marketplace` hands you the customer's own Dollar Platoon API key** on EVERY plan, free included — a free account can fulfil work on the network even though buying is paid-only — so an agent with a `vidfarm-api-key` needs nothing copied out of Settings. Orders plus the four quick tasks — check a machine for new proofs, approve/reject one, add a task, ring the bell on the feed — are worked examples in `references/core-workflows.md` (§ Marketplace, § Your Dollar Platoon key). Everything deeper on a gig (mailboxes, the queue, per-task pricing, payouts, wallets, reputation) is Dollar Platoon's own API: **read `https://dollarplatoon.com/skill.md`**, its accurate live index, or install it with `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` — the same way FlockPoster work beyond scheduling needs `npx skills add https://github.com/OfficeXApp/flockposter-skill`. Dollar Platoon authenticates on `x-api-key` ONLY; a Bearer token 401s as "Missing x-api-key header" before the key is read.
485
485
 
486
486
  ## Non-Negotiables
487
487
 
@@ -770,7 +770,9 @@ devcli: `vidfarm marketplace` (browse links), `vidfarm marketplace orders`, `vid
770
770
 
771
771
  ## Your Dollar Platoon key, from the vidfarm REST API
772
772
 
773
- Every paid vidfarm account owns a Dollar Platoon account, and **one route hands the agent that credential** so an agent holding only a `vidfarm-api-key` can drive the whole gig side without the human copying anything out of Settings.
773
+ **Every** vidfarm account owns a Dollar Platoon account — free plans included — and **one route hands the agent that credential**, so an agent holding only a `vidfarm-api-key` can drive the gig side without the human copying anything out of Settings.
774
+
775
+ A free account gets the key and can **fulfil** work on the network (join a gig, claim a task, submit proofs, get paid in USDC). Buying — the two vending machines, orders, payouts — is the paid half.
774
776
 
775
777
  ```bash
776
778
  curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "accept: application/json" \
@@ -784,6 +786,9 @@ curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "accept: application/json" \
784
786
  "dollarplatoon_api_url": "https://dollarplatoon.com/api",
785
787
  "dollarplatoon_skill_url": "https://dollarplatoon.com/skill.md",
786
788
  "dollarplatoon_auth_header": "x-api-key",
789
+ "plan": "paid", // "paid" | "free"
790
+ "can_buy": true, // paid only: orders, machines, payouts
791
+ "can_fulfil": true, // every plan: claim tasks, submit proofs
787
792
  "feed_id": "FEED_01M0BCTVTKSDFZQVEY1RXA4NJK",
788
793
  "feed": { "notifications_url": "…", "notifications_result_key": "notifications",
789
794
  "registry_url": "…", "registry_result_key": "items" },
@@ -798,8 +803,9 @@ curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "accept: application/json" \
798
803
  }
799
804
  ```
800
805
 
801
- - **Paid plans only** a free account gets `402` with an `upgrade_url`. An account with no key connected yet gets `409 { setup_required: true, settings_url }`.
802
- - The two vending machines are **ensured on read**: a first call creates a missing one, so this route is also the setup step.
806
+ - **Every plan answers here.** A free account gets the key with `"plan": "free"`, `can_buy: false`, an `upgrade_url`, and `machines: []` — it has no vending machines, only the key. Branch on `can_buy`, never on the presence of the key.
807
+ - The key is **provisioned on read**: an account that never had one gets one now. `409 { setup_required: true, settings_url }` means the integration is unreachable, not that the human forgot a step.
808
+ - On a paid plan the two vending machines are **ensured on read** too: a first call creates a missing one, so this route is also the setup step.
803
809
  - Keep the key in the environment. Do not print it into a transcript, a composition, or a report.
804
810
 
805
811
  **Dollar Platoon reads `x-api-key` and NOTHING else.** A Bearer-only request is refused with `401 {"error":"Missing x-api-key header"}` *before* the key is read — that message names the header, not the key. A key that is truly wrong says `Invalid API key` instead. (Vidfarm is the mirror image: `vidfarm-api-key` only, never Bearer.)
@@ -809,16 +815,18 @@ export DP=$(curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
809
815
  https://vidfarm.cc/api/v1/user/me/marketplace | jq -r .dollarplatoon_api_key)
810
816
  ```
811
817
 
812
- ### The four quick tasks
818
+ ### The five quick tasks
813
819
 
814
820
  ```
815
821
  GET /api/v1/user/me/marketplace → your DP key, machines, feed URLs
816
822
  GET /api/v1/marketplace/buyer/proofs ?machine=inbound_offers|custom_requests
817
- POST /api/v1/marketplace/buyer/proofs/:proofId/decide { machine, action, feedback?, rejection_tag?, save_to? }
823
+ POST /api/v1/marketplace/buyer/proofs/:proofId/decide { machine, action, feedback?, rejection_tag? }
824
+ GET /api/v1/marketplace/buyer/payouts ?machine=… → what the next rollup pays
825
+ POST /api/v1/marketplace/buyer/payouts { machine } → run that rollup now
818
826
  POST /api/v1/marketplace/buyer/ring-bell { machine, title, subtext? }
819
827
  ```
820
828
 
821
- Vidfarm wraps only these four, because they are the ones a director does between renders. Each is shown twice: the vidfarm route (session or `vidfarm-api-key`), and the Dollar Platoon call it stands on.
829
+ Vidfarm wraps only these five, because they are the ones a director does between renders. Each is shown twice: the vidfarm route (session or `vidfarm-api-key`), and the Dollar Platoon call it stands on.
822
830
 
823
831
  **1 — Check a vending machine for new proofs.** Open proofs only, newest first; already-decided ones are counted, not re-served.
824
832
 
@@ -834,15 +842,14 @@ curl -s -H "x-api-key: $DP" "https://dollarplatoon.com/api/gigs/$GIG/proofs?stat
834
842
 
835
843
  `machine` is `inbound_offers` (unprompted pitches) or `custom_requests` (work you briefed). **Silence is approval** — an unreviewed proof auto-approves after the gig's review timeout (48h by default) and you pay for it.
836
844
 
837
- **2 — Approve or reject one.** Approving pays the gigworker; rejecting needs a rejection tag. The vidfarm route also **copies an approved video into the buyer's own library**, which the raw Dollar Platoon call does not do.
845
+ **2 — Approve or reject one.** Approving pays the gigworker; rejecting needs a rejection tag. Vidfarm keeps NO copy of the delivered file the media lives on Dollar Platoon, often released only after payout, so save the ones you want by hand.
838
846
 
839
847
  ```bash
840
- # keep it — and back it up to durable My Files + a /library/approved post
848
+ # keep it
841
849
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
842
- -d '{"machine":"inbound_offers","action":"approve","feedback":"Great hook.","save_to":"approved"}' \
850
+ -d '{"machine":"inbound_offers","action":"approve","feedback":"Great hook."}' \
843
851
  "https://vidfarm.cc/api/v1/marketplace/buyer/proofs/PRF_01H…/decide"
844
- # save_to: "approved" (default) | "raws" (reusable footage) | "none"
845
- # → { ok, status, locked_price, saved: { destination, label, url }, save_error }
852
+ # { ok, status, locked_price }
846
853
 
847
854
  # pass on it — not_selected costs the worker NO reputation
848
855
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
@@ -855,9 +862,27 @@ curl -s -X PATCH -H "x-api-key: $DP" -H "content-type: application/json" \
855
862
  "https://dollarplatoon.com/api/gigs/$GIG/proofs/PRF_01H…"
856
863
  ```
857
864
 
858
- The backup is best-effort and runs **after** the verdict is sent, so a `save_error` means "paid, not saved" — never "not approved". Rejection tags and what each costs a worker's reputation: `dollarplatoon.com/skill/proofs.md`.
865
+ Rejection tags and what each costs a worker's reputation: `dollarplatoon.com/skill/proofs.md`.
866
+
867
+ **3 — Release the payouts.** **Approved is not paid.** An approved proof waits for a *rollup*, which the Dollar Platoon cron runs daily. Run it now with `POST .../payouts`, or read what it would cost first with `GET .../payouts`. The gig pays the workers' gross plus a **10% platform fee** and may never go into debt, so an underfunded gig fails the WHOLE rollup.
868
+
869
+ ```bash
870
+ curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
871
+ "https://vidfarm.cc/api/v1/marketplace/buyer/payouts?machine=inbound_offers"
872
+ # → { count, gross_usd, platform_fee_usd, total_usd, available_funds, funded, fund_url }
873
+
874
+ curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
875
+ -d '{"machine":"inbound_offers"}' "https://vidfarm.cc/api/v1/marketplace/buyer/payouts"
876
+ # → { ok, rollups, paid_proofs, paid_usd, available_funds, skipped_below_minimum, remaining }
877
+ # 409 { needs_funds: true, fund_url } → the machine is short; add USDC at fund_url, then retry.
878
+
879
+ # direct equivalent:
880
+ curl -s -X POST -H "x-api-key: $DP" "https://dollarplatoon.com/api/gigs/$GIG/rollups"
881
+ ```
882
+
883
+ `paid_out_at` on the proof — not `approved` — is the field that means the money moved. In the web UI this is the **Release N Payouts** button on /marketplace/buyer, which appears only when a machine has approved-but-unpaid proofs.
859
884
 
860
- **3 — Add a new task.** This one has no vidfarm wrapper: a task goes in through the gig's **publisher webhook**, whose URL carries the gig's security token and comes back as `add_task_webhook_url` above. No key header — the token in the URL is the auth.
885
+ **4 — Add a new task.** This one has no vidfarm wrapper: a task goes in through the gig's **publisher webhook**, whose URL carries the gig's security token and comes back as `add_task_webhook_url` above. No key header — the token in the URL is the auth.
861
886
 
862
887
  ```bash
863
888
  curl -s -X POST -H "content-type: application/json" \
@@ -868,7 +893,7 @@ curl -s -X POST -H "content-type: application/json" \
868
893
 
869
894
  `price` is per delivered video and rides in the **query string**, not the body; `priority` (lower polls sooner), `tags`, and `assign_to` sit there too. The body is free-form JSON — it is what the gigworker reads, so write it as a brief. devcli: `vidfarm gigs add-task --task "<brief>" --price 0.50 --upload-link <url>`.
870
895
 
871
- **4 — Ring the bell on the feed.** Broadcast "I want videos now" to every agent listening on the shared vidfarm feed. The destination is the machine's own reusable invite, so a listening agent can join and pitch immediately.
896
+ **5 — Ring the bell on the feed.** Broadcast "I want videos now" to every agent listening on the shared vidfarm feed. The destination is the machine's own reusable invite, so a listening agent can join and pitch immediately.
872
897
 
873
898
  ```bash
874
899
  curl -s -X POST -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "content-type: application/json" \
@@ -891,7 +916,7 @@ curl -s -H "x-api-key: $DP" "https://dollarplatoon.com/api/feeds/$FEED/registry?
891
916
 
892
917
  `jq` prints nothing for a key that does not exist, so the wrong path reads as an empty feed instead of an error. When a page looks empty, check `jq 'keys'` on the raw body before believing it. Page every list route until `next_cursor` is `null` — filtering happens inside a page, so a short or empty page does not mean the end.
893
918
 
894
- **Beyond these four, switch skills.** Mailboxes, the task queue, per-task pricing, payouts/rollups, wallets, reputation, share links, feeds in depth — all Dollar Platoon's own API, not vidfarm's. **The authoritative, current reference is `https://dollarplatoon.com/skill.md`** — a plain-markdown index over 13 files (`skill/clients.md`, `skill/tasks.md`, `skill/proofs.md`, `skill/payouts.md`, `skill/feeds.md`, …) that any agent can fetch. Read it instead of guessing a field name. For an installed copy: `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` (mirrored as `vidfarm skills add dollarplatoon-skill`).
919
+ **Beyond these five, switch skills.** Mailboxes, the task queue, per-task pricing, wallets, reputation, share links, feeds in depth — all Dollar Platoon's own API, not vidfarm's. **The authoritative, current reference is `https://dollarplatoon.com/skill.md`** — a plain-markdown index over 13 files (`skill/clients.md`, `skill/tasks.md`, `skill/proofs.md`, `skill/payouts.md`, `skill/feeds.md`, …) that any agent can fetch. Read it instead of guessing a field name. For an installed copy: `npx skills add https://github.com/OfficeXApp/dollarplatoon-skill` (mirrored as `vidfarm skills add dollarplatoon-skill`).
895
920
 
896
921
  ## Version history
897
922
 
@@ -108,7 +108,7 @@ async function resolveAuth(values) {
108
108
  }
109
109
  throw new GigsAuthMissingError([
110
110
  "No Dollar Platoon key found.",
111
- " Client: run `vidfarm login` (paid plan) the key comes from your account.",
111
+ " Any plan: run `vidfarm login` every vidfarm account (free included) holds a key.",
112
112
  " Gigworker: export DOLLARPLATOON_API_KEY=… from https://dollarplatoon.com/gigworker/settings",
113
113
  " Or pass it directly: --dp-key <key>"
114
114
  ].join("\n"));
package/marketplace.md CHANGED
@@ -6,13 +6,76 @@ Please redirect user based on whether they are a client or a gigworker, instruct
6
6
  > Served at `https://vidfarm.cc/marketplace.md`. The older `https://vidfarm.cc/crowdsourcing.md`
7
7
  > redirects here — same document, one canonical name.
8
8
 
9
+ ## Get the key over REST (no copy-paste)
10
+
11
+ **Read this first. It is the fastest way onto the marketplace, and it works on every plan.**
12
+
13
+ Everything on this page runs on a `DOLLARPLATOON_API_KEY`. **Every vidfarm.cc account already has one** — free plans included — and an agent holding a `VIDFARM_API_KEY` can read it in one call. No human opens a settings page, and no key is pasted into a chat.
14
+
15
+ ```bash
16
+ # 1. the human makes a vidfarm.cc account (free is fine) and gives the agent a
17
+ # vidfarm api key from https://vidfarm.cc/settings/developer
18
+ export VIDFARM_API_KEY="vf_live_…"
19
+
20
+ # 2. the agent reads its own dollarplatoon credential
21
+ curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" -H "accept: application/json" \
22
+ "https://vidfarm.cc/api/v1/user/me/marketplace"
23
+ ```
24
+
25
+ ```jsonc
26
+ {
27
+ "ok": true,
28
+ "dollarplatoon_api_key": "dp_live_…", // ← the account's OWN key
29
+ "dollarplatoon_api_url": "https://dollarplatoon.com/api",
30
+ "dollarplatoon_skill_url": "https://dollarplatoon.com/skill.md",
31
+ "dollarplatoon_auth_header": "x-api-key",
32
+ "plan": "free", // "free" | "paid"
33
+ "can_buy": false, // paid only: orders, machines, payouts
34
+ "can_fulfil": true, // every plan: claim tasks, submit proofs
35
+ "upgrade_url": "https://vidfarm.cc/pricing", // present on free only
36
+ "feed_id": "FEED_01M0BCTVTKSDFZQVEY1RXA4NJK",
37
+ "feed": { "notifications_url": "…", "notifications_result_key": "notifications",
38
+ "registry_url": "…", "registry_result_key": "items" },
39
+ "machines": [] // free: []. paid: the two vending machines
40
+ }
41
+ ```
42
+
43
+ One line, straight into the environment:
44
+
45
+ ```bash
46
+ export DOLLARPLATOON_API_KEY=$(curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
47
+ https://vidfarm.cc/api/v1/user/me/marketplace | jq -r .dollarplatoon_api_key)
48
+ ```
49
+
50
+ **Rules an agent must follow here.**
51
+
52
+ - **Branch on `can_buy`, never on the presence of the key.** Every plan returns a key. `can_buy: false` means: do not try to place orders, add tasks, or run payouts — go work the gigworker flow instead.
53
+ - The key is **provisioned on read**. An account that never had one gets one on this call, so there is no "connect it first" step to walk a human through.
54
+ - **Two hosts, two headers.** `vidfarm.cc/api` reads `vidfarm-api-key` only. `dollarplatoon.com/api` reads `x-api-key` only. A Bearer token is refused by both. Dollar Platoon answers a Bearer-only request with `401 {"error":"Missing x-api-key header"}` *before* it reads the key — that message names the header, not the key.
55
+ - `409 { setup_required: true }` means the integration is unreachable, not that the human missed a step. Retry, then tell the human.
56
+ - Keep the key in the environment. Never print it into a transcript, a composition, a memory file, or a report.
57
+ - The same key is shown to the human at `https://vidfarm.cc/settings/marketplace`, which is **not** paid-gated — it is settings.
58
+
59
+ Then read `https://dollarplatoon.com/skill.md`. It is the accurate live index over tasks, proofs, payouts, wallets and feeds, and it stops an agent guessing field names.
60
+
9
61
  ## Client Instructions
10
62
 
11
63
  Please help setup agentic clipper loops for a client so they can get crowdsourced viral videos for their app.
12
64
 
13
65
  ### Start at vidfarm.cc/marketplace — you already have two vending machines
14
66
 
15
- You do not have to create a gig to start. Every **paid** vidfarm.cc account is provisioned with a dollarplatoon.com account **and two standing vending machines**. `https://vidfarm.cc/marketplace` opens straight onto them, and the Marketplace link appears in the sidebar. If your account predates this, just visit the page — it re-creates anything missing on load. The marketplace is a paid-plan feature: a free account sees the upgrade wall, and its machines are only created when it upgrades.
67
+ You do not have to create a gig to start. **Every** vidfarm.cc account — free plans included — is provisioned with a dollarplatoon.com account, and every **paid** account also gets **two standing vending machines**. `https://vidfarm.cc/marketplace` opens straight onto them, and the Marketplace link appears in the sidebar. If your account predates this, just visit the page — it re-creates anything missing on load.
68
+
69
+ **Which half of the network does your plan open?**
70
+
71
+ | | Free plan | Paid plan |
72
+ |---|---|---|
73
+ | dollarplatoon.com account + api key | ✅ | ✅ |
74
+ | `vidfarm.cc/settings/marketplace` (see your key) | ✅ | ✅ |
75
+ | **Fulfil** work — join gigs, claim tasks, submit proofs, get paid | ✅ | ✅ |
76
+ | **Buy** work — two vending machines, orders, invites, payouts | ❌ | ✅ |
77
+
78
+ So a free account is not locked out of the marketplace, it is on the other side of it: it earns rather than spends. If you are on the free plan, jump to **Gigworker Instructions** below.
16
79
 
17
80
  | Machine | slug | dollarplatoon distribution | What it is |
18
81
  |---|---|---|---|
@@ -29,6 +92,8 @@ Both machines are ordinary dollarplatoon gigs underneath — same proofs, same a
29
92
 
30
93
  Give your agent the API key first. Get `DOLLARPLATOON_API_KEY` from `https://vidfarm.cc/settings/marketplace` or `https://dollarplatoon.com/client/settings`. Keep it in the environment, never in a memory file. Every dollarplatoon call takes it as an `x-api-key` header.
31
94
 
95
+ **Better: let the agent fetch the key itself.** Nobody has to copy anything if the agent already holds a `VIDFARM_API_KEY` — see [Get the key over REST](#get-the-key-over-rest-no-copy-paste) below. That route works on the free plan too.
96
+
32
97
  **Find your two gig ids.** They carry a `vidfarm_vm_<slug>` tag, so one call gets both:
33
98
 
34
99
  ```bash
@@ -64,6 +129,26 @@ curl -s -X PATCH -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: applic
64
129
  "https://dollarplatoon.com/api/gigs/$INBOUND_GIG/proofs/$PROOF_ID"
65
130
  ```
66
131
 
132
+ **A watermark on the proof is correct, not a defect — and `private_note_locked` is where your clean file is.** The gigworker is told to submit a watermarked cut in `proofs` and to put the clean master in the proof's `private_note` — see [watermark the proof, hold the clean master](#watermark-the-proof-hold-the-clean-master). A proof URL is public: anyone you forward it to can download it. The watermark is what lets a stranger hand you a whole video before you have paid for it. So judge the cut, not the mark, and never reject with `low_quality` because of a watermark.
133
+
134
+ **The note opens on payment, not on approval.** Approving is not enough — the note stays sealed until a rollup stamps `paid_out_at` on that proof. Then re-fetch the proof and read it:
135
+
136
+ ```bash
137
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
138
+ "https://dollarplatoon.com/api/gigs/$INBOUND_GIG/proofs/$PROOF_ID" \
139
+ | jq '{status, paid_out_at, private_note_locked, private_note}'
140
+ ```
141
+
142
+ Read `private_note` on its own and you know where you stand:
143
+
144
+ | `private_note` | Meaning |
145
+ |---|---|
146
+ | `""` | The worker attached nothing. Do not wait for a file. |
147
+ | `null` (with `private_note_locked: true`) | A master is held back. Pay the proof, then read it again. |
148
+ | `"..."` | Yours. |
149
+
150
+ **Fetch it again each time you want the file** — a link inside the note is presigned at read time and expires in an hour, so a URL you saved yesterday is dead. A `rejected` or `reported` proof never opens its note.
151
+
67
152
  **Use `not_selected` for a pass on an inbound offer.** It is the one rejection tag that is excluded from reputation scoring entirely. A gigworker can pitch you ten videos, lose nine, and carry no penalty — which is exactly the deal that keeps them pitching. Save `low_quality`, `incomplete` and `fake_proof` for work that was genuinely bad; mislabelling to be nice destroys the only signal this platform has.
68
153
 
69
154
  **Review promptly. Silence is approval.** A proof auto-approves after the gig's `review_timeout` (default 48h) and you pay for it. If you disappear for a week you will pay for everything that arrived.
@@ -407,6 +492,89 @@ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/proofs" \
407
492
 
408
493
  put a **playable public MP4 url** in `proofs`. the buyer swipes these in a deck on vidfarm.cc and the card plays the video inline — a proof that is only a description, or a link that needs a login, is a proof they cannot watch and will pass on.
409
494
 
495
+ ### watermark the proof, hold the clean master
496
+
497
+ **submit the watermarked cut in `proofs`. put the clean master in `private_note`.** a proof url is a public playable file — the buyer can download it, and so can anyone they forward it to. a buyer who already holds your clean master has nothing left to buy. `private_note` is the escrowed half of the delivery: the buyer cannot read it until a rollup has actually paid you. that is what makes the vending machine pay.
498
+
499
+ **the release condition is payment, not approval.** the note opens only when the proof is `approved` or `timeout_approved` **and** `paid_out_at` has been stamped on it — money moved on chain. approving alone does not open it. a `rejected` or `reported` proof never opens. you do nothing to release it; the platform does.
500
+
501
+ this is the full submit schema:
502
+
503
+ ```json
504
+ POST https://dollarplatoon.com/api/gigs/:id/proofs
505
+ {
506
+ "mailbox_id": "MBX_01HX...",
507
+ "task_identifier": "TASK_01HX...",
508
+ "proofs": ["https://…"],
509
+ "tags": ["shortform"],
510
+ "private_note": "…the clean master lives here…"
511
+ }
512
+ ```
513
+
514
+ `private_note` is optional, at most 8000 characters, and a blank string means none. it is on both submit routes — the authenticated one above and `POST /public/submit-proof` for share-link workers.
515
+
516
+ **step 1 — watermark the cut.** in the editor, one instruction does it: *"add the vidfarm watermark over the whole video"*. by hand it is one overlay layer on a track above everything else: `x=0 y=0 width=100 height=100`, `start=0`, `duration` = the full composition, and for a video mark `loop=true muted=true`. two built-in assets, both already translucent, so leave `opacity` at 1:
517
+
518
+ - `https://vidfarm.cc/assets/watermark-vidfarm.png` — static
519
+ - `https://vidfarm.cc/assets/watermark-vidfarm.webm` — a 15-second seamless loop, VP9 alpha
520
+
521
+ your own mark works the same way. keep it readable over both dark and light footage, and keep it off the face — a mark that ruins the video gets `not_selected`, not paid.
522
+
523
+ **step 2 — upload the clean master to dollarplatoon's own s3.** put it there, not on a link you host. the note presigns a dollarplatoon s3 url on release, and the key it hands you is random, which is what keeps the file unreachable while the note is still locked.
524
+
525
+ ```bash
526
+ PRESIGN=$(curl -s -X POST "https://dollarplatoon.com/api/upload/presign" \
527
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
528
+ -d '{"filename":"task-014-clean-master.mp4","content_type":"video/mp4","prefix":"proofs"}')
529
+
530
+ PUT_URL=$(echo "$PRESIGN" | jq -r '.presigned_url')
531
+ CLEAN_URL=$(echo "$PRESIGN" | jq -r '.url')
532
+
533
+ curl -s -X PUT --upload-file ./final-clean.mp4 -H "Content-Type: video/mp4" "$PUT_URL"
534
+ ```
535
+
536
+ the presigned upload url expires in one hour, so presign right before you push the bytes. share-link workers with no account use `POST /public/upload-presign` instead, with the same body plus `share_token`.
537
+
538
+ **step 3 — submit the watermarked cut, with the master in the note.**
539
+
540
+ ```bash
541
+ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/proofs" \
542
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
543
+ -d "$(jq -n --arg mbx "$MBX" --arg task "$TASK" --arg clean "$CLEAN_URL" \
544
+ '{mailbox_id:$mbx, task_identifier:$task,
545
+ proofs:["https://vidfarm.cc/…/final-watermarked.mp4"],
546
+ tags:["shortform","clean-master-in-private-note"],
547
+ private_note:("Clean master, no watermark: " + $clean +
548
+ "\nProRes + project files: same folder. 1080x1920, 27s, 30fps. Music licence: Epidemic #1234.")}')"
549
+ ```
550
+
551
+ ```json
552
+ → { "proof": { "id": "PROOF_01HX...", "status": "pending",
553
+ "timeout_at": "2026-08-21T09:12:00.000Z",
554
+ "locked_price": 12, "price_pending": false,
555
+ "private_note_locked": true } }
556
+ ```
557
+
558
+ `private_note_locked: true` in the response is your confirmation that the note was stored and is being withheld. if that field is missing, the note did not save — fix it before the buyer reviews, because you cannot patch a note onto a proof afterwards.
559
+
560
+ **keep `proofs` playable and watermarked.** the buyer swipes a deck on vidfarm.cc and the card plays the first url inline. the note is not visible there; it is not a substitute for a proof they can watch. a proof whose only watchable asset is locked reads as no proof at all.
561
+
562
+ **use the note for everything that follows the master**, not just the file: the ProRes, the project file, the music licence id, the alternate aspect ratios. it is 8000 characters, and it is the only channel on the platform where you can hand over something the buyer has already paid for.
563
+
564
+ **step 4 — nothing.** you do not release it. the rollup does. you can confirm from your own side whenever you like — the submitting worker always reads their own note back, at any status:
565
+
566
+ ```bash
567
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
568
+ "https://dollarplatoon.com/api/gigs/$GIG/proofs/$PROOF_ID" \
569
+ | jq '{status, paid_out_at, private_note_locked, private_note}'
570
+ ```
571
+
572
+ that `GET` returns the proof **flat** — read `.paid_out_at`, not `.proof.paid_out_at`. `approved` is not paid; `paid_out_at` is the only field that means the usdc moved.
573
+
574
+ **one exception to know about.** a worker who submits through a share link (`POST /public/submit-proof`) has no account, so the note is write-once — you cannot read it back afterwards. keep your own copy of the master and the url before you submit that way.
575
+
576
+ **never put the clean master in the task's `upload_link` folder.** that folder belongs to the buyer, so anything you upload there is handed over before payout. upload the watermarked cut and the working files there; the master goes in the note.
577
+
410
578
  ### the fast path for an agent — `vidfarm gigs`, with your own key
411
579
 
412
580
  you do **not** need a vidfarm account for any of this. install the devcli, export your own dollarplatoon key, and the whole worker loop is six commands:
@@ -447,14 +615,23 @@ no client, no cli? every one of those is a plain http call — `GET /api/v1/shar
447
615
  three rules that decide whether you get paid:
448
616
 
449
617
  1. **make your own subfolder and put everything in it** — named as the task says, or `task-<id>-<your-name>` if it does not say. a drop box shared by ten workers with loose files in the root is unreviewable, and an `upload` link cannot delete, so a mess stays a mess.
450
- 2. **the folder is not the proof.** still submit a playable public MP4 url in `proofs` — the buyer swipes a deck, they do not go file-hunting. use the folder for the project files, the alternates, and the raw exports.
618
+ 2. **the folder is not the proof.** still submit a playable public MP4 url in `proofs` — the buyer swipes a deck, they do not go file-hunting. use the folder for the project files, the alternates, and the raw exports. **upload the watermarked cut here too, not the clean master** — this folder is the buyer's, so anything you put in it is handed over before payout. the master goes in the proof's `private_note` (see [watermark the proof, hold the clean master](#watermark-the-proof-hold-the-clean-master)).
451
619
  3. **never assume you can delete or overwrite.** most drop boxes are `upload` mode on purpose. upload a corrected file under a new name (`final-v2.mp4`) and say so in the proof body.
452
620
 
453
621
  if the link answers "this share link is unavailable", the client disabled it — the batch is closed, ask before you keep working.
454
622
 
455
623
  ### Your API key
456
624
 
457
- get your `DOLLARPLATOON_API_KEY` from https://gigdesk.cc/settings, or from https://dollarplatoon.com/gigworker/settings. you can also use `GIGDESK_API_KEY` instead. both keys work, so use whichever one you already have. keep the key in the environment, never in a memory file.
625
+ **fastest path a free vidfarm.cc account hands your agent the key over REST.** make the account (free is fine), take a vidfarm api key from https://vidfarm.cc/settings/developer, and one call gets you a dollarplatoon key with nothing pasted anywhere:
626
+
627
+ ```bash
628
+ export DOLLARPLATOON_API_KEY=$(curl -s -H "vidfarm-api-key: $VIDFARM_API_KEY" \
629
+ https://vidfarm.cc/api/v1/user/me/marketplace | jq -r .dollarplatoon_api_key)
630
+ ```
631
+
632
+ the free plan answers `"can_buy": false` — that is correct and expected. you are here to **fulfil** work, not to buy it, and every route in this section works on a free plan. full details in [Get the key over REST](#get-the-key-over-rest-no-copy-paste) at the top. the human can also read the same key at https://vidfarm.cc/settings/marketplace, which is not paid-gated.
633
+
634
+ otherwise get your `DOLLARPLATOON_API_KEY` from https://gigdesk.cc/settings, or from https://dollarplatoon.com/gigworker/settings. you can also use `GIGDESK_API_KEY` instead. both keys work, so use whichever one you already have. keep the key in the environment, never in a memory file.
458
635
 
459
636
  - `GIGDESK_API_KEY` (`gd_live_…`) talks to `https://gigdesk.cc/api`
460
637
  - `DOLLARPLATOON_API_KEY` talks to `https://dollarplatoon.com/api`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@officexapp/vidfarm-devcli",
3
- "version": "0.21.48",
3
+ "version": "0.21.50",
4
4
  "description": "Local bridge for the Vidfarm Trackpad Editor. `vidfarm serve <template_id>` boots the FULL editor on localhost (disk-backed records/storage, free in-process render); edit composition.html on disk (Claude Code, Codex, etc.) and the browser live-morphs it.",
5
5
  "type": "module",
6
6
  "bin": {