Toborlife Marketplace: End-to-End Flow¶
Summary¶
The Toborlife marketplace lets organizations sell robot datasets they hold on Toboverse and lets other organizations license and import them, with Toborlife in the middle of every deal. It runs at a Toboverse subdomain (proposed: market.toboverse.ai) and is built on the existing RDS database and S3 video bucket rather than copying data into a new system.
Three roles use it:
- Buyer: an organization that searches, previews, licenses and imports datasets. It may be an existing Toborlife customer or a new sign-up.
- Seller: an organization that lists a chosen set of its episodes for sale. It may already store data on Toboverse or be a new organization uploading for the first time.
- Admin (Toborlife): holds buyer payments until delivery is accepted and takes a commission.
This document walks through each flow in order and names the component, table and bucket involved at every step.
Features¶
The first version ships the necessary features; the optional ones can follow.
Necessary
| Feature | What it does |
|---|---|
| Organization accounts | Buyers and sellers sign in with AWS Cognito and act for an organization |
| Listings from a set | A seller lists a set or group with title, description, visibility, license options and price |
| Search and filters | Robot model, task, frame rate, sensors, hours, format, price |
| Previews before purchase | Short sample videos and synced multi-sensor playback |
| Standard licenses and contracts | Click-to-accept templates; e-signature for custom deals |
| Held payment and payout | Toborlife holds the buyer's money until the acceptance window closes, then pays the seller minus commission |
| Delivery in standard formats | LeRobot or HDF5 by download, S3 copy or SDK |
| Audit trail | Every order step written to audit_logs |
Optional
| Feature | What it does |
|---|---|
| Automated QA before going live | Unprocessed, trashed or not-ready episodes block a listing |
| Data requests | A buyer posts requirements, budget and deadline; sellers reply with quotes |
| Requirement-based ranking | Listings ranked by the robot type, tasks and formats a buyer says they need |
| Free sample datasets | Small public samples published on Hugging Face to attract buyers |
| Quality score on listings | Average aggregate_score shown on each listing |
| Import into the buyer's org | Existing customers receive purchases as episodes in their own workspace |
| Consent and provenance records | Proof of who collected the data and under what consent |
End-to-end flow¶
Every listing passes automated QA before buyers can see it, and every payment is held by Toborlife until the buyer accepts the delivery.
flowchart TD
subgraph Seller
S1["Sign in or register<br/>AWS Cognito"] --> S2["Seller setup<br/>Agreement, payout details"]
S2 --> S3["Create listing<br/>Pick a set, set price"]
S5["Fix and resubmit<br/>Reasons from QA"]
S10["Receive payout<br/>Price minus commission"]
end
subgraph Toborlife["Toborlife platform and admin"]
T4["Publisher and previews<br/>Facets, QA, sample clips"] --> T5{"QA passes?"}
T6["Listing live<br/>Indexed in OpenSearch"]
T8["Hold payment, export<br/>Grant access, package"]
end
subgraph Buyer
B1["Sign in or register<br/>AWS Cognito"] --> B7["Search and preview<br/>OpenSearch, CloudFront"]
B7 --> B8["Sign license and pay<br/>Contract, held payment"]
B9["Download or import<br/>Signed URL, S3 copy, SDK"]
end
S3 --> T4
T5 -- no --> S5
S5 --> S3
T5 -- yes --> T6
T6 --> B7
B8 --> T8
T8 --> B9
B9 -- "7-day window" --> S10
Read each lane top down: the seller's work on the left, Toborlife's checks and holds in the middle, the buyer's steps on the right. A rejected listing loops back to the seller; after the acceptance window, the payout goes to the seller.
Flow 1: Sign in¶
Every buyer, seller and admin enters through the same AWS Cognito login; a role is a permission on an account, not a separate account.
- The user opens the marketplace subdomain.
- The app redirects to AWS Cognito.
- An existing Toborlife customer signs in with their current Cognito account. The platform matches them to
usersand to an activeorganization_membersrow (removed_at IS NULL). - A new user registers in Cognito and a
usersrow is added. They either create an organization, becoming its first Owner, or join one by accepting an invite throughaccept_member_invite(token, user_id). - Cognito returns a signed token carrying the user's identity; the user picks which of their orgs to act for.
- On every request the API opens a transaction as
tobor_app, runsSET LOCAL app.current_organdapp.current_user, and resolves permissions fromroles,role_permissionsanduser_permissions. RLS then limits every tenant read and write to that org.
One organization can hold both buyer and seller roles at the same time.
Flow 2: Seller onboarding¶
An organization can list data once it has accepted the seller agreement and added payout details.
- In the seller studio, an Owner (or a member whose role carries the new
marketplace.sellpermission) selects "Start selling". The API calls a marketplace function that creates the org'smarketplace.seller_accountsrow. - The seller adds payout bank details with the marketplace payment provider; the reference is stored in
marketplace.seller_accounts. The existing billing tables are not touched. - The seller accepts the seller agreement: they own the data and hold consent from anyone recorded in it. The acceptance and agreement version are written to
audit_logs. - Members who should list data get
marketplace.sellthroughrole_permissionsoruser_permissions; role changes are recorded inrole_change_logs. The org can now publish listings.
Flow 3: Publishing a listing¶
A listing points to a live set, so buyers always see the episodes the set holds now; each order records the exact episodes it delivered.
- Data in. Existing customers already have episodes organised into sets and groups. New orgs upload through
upload_partsinto thes3bucket, then link episodes into a set (episode_sets). - Listing. The seller picks a set (or a group) and adds a title, description, visibility (public, private or invite-only), license options and prices. The API calls
marketplace.publish_listing(), which writeslistings, alisting_versionsrow holding the set id (or group id) with statusprocessing,listing_pricesand anoutbox_eventsrow. - Jobs started. The API starts the publisher and preview builder, each with
app.current_orgset to the seller org. - Publisher worker. It reads the set's live episodes from
episode_sets(for a group, throughset_groupsfirst) and joinsepisodes,episode_metadata,episode_tasks,robotsandrobot_models. QA fails the listing if any episode is trashed (deleted_atset), has astatusother thanprocessed, or has not clearedreadiness_state. Facets record robot models, frame rate, degrees of freedom, sensors, tasks, hours, episode count and the averageaggregate_score. - Preview builder. It picks representative episodes, reads each one's mp4 from the
s3bucket, cuts short samples with FFmpeg plus Rerun files, writes them topreviewsand records them inlisting_previews. - Go live. If QA passes, the status becomes
liveand another outbox event is written. If it fails, the listing returns to the seller with the reasons. - Search sync. The worker reads the outbox events and updates OpenSearch, so the listing becomes searchable.
When episodes are added to or removed from the set, the publisher reruns QA and refreshes facets and previews before the change reaches buyers. Past buyers keep exactly what their order delivered.
Flow 4: Discovery and preview¶
Buyers see listings ranked by their stated requirements and can watch samples, but never touch the videos bucket before paying.
- (Optional) On a first visit, the buyer answers a few questions: robot type, tasks, formats, budget. These are saved to their profile and used to rank listings.
- The buyer portal asks the API for listings. Search and filters go to OpenSearch, which returns matching listing IDs; listing details come from the marketplace schema on the read replica, never from seller tables.
- Visibility rules apply: private listings show only to invited organizations.
- Opening a listing streams previews from the
previewsbucket through CloudFront, or opens a multi-sensor sample in the embedded Rerun viewer. - (Optional) If nothing fits, the buyer posts a data request (
marketplace.data_requests) with requirements, budget and deadline. Sellers are emailed through SES and reply with offers inmarketplace.quotes. An accepted quote enters Flow 5 as an order.
Flow 5: Purchase to payout¶
The order workflow (Step Functions) runs each purchase from checkout to payout; the buyer's money is held until the acceptance window closes.
sequenceDiagram
participant B as Buyer (portal)
participant A as Marketplace API
participant W as Order workflow (Step Functions)
participant X as External (payment, Dropbox Sign)
participant D as Database (RDS primary)
participant P as Export packager (S3)
B->>A: Checkout
A->>D: Create order
A->>W: Start workflow
W->>X: Create contract
X-->>B: Accept or e-sign
X-->>W: Signed (webhook)
W->>P: PDF to contracts
W->>X: Charge, hold funds
X-->>W: Payment succeeded
W->>D: Grant access
W->>P: Start export job
P-->>W: Export ready
W->>B: Download link
Note over B,P: Acceptance window, about 7 days, payout waits
W->>X: Release payout
W->>D: Order complete
Access is written only after the signed-contract and payment webhooks arrive; the payout is released after the acceptance window, not at checkout.
- Checkout. The buyer picks a listing version and license, such as commercial non-exclusive. The API confirms the listing is still live.
- Order created. The API writes
marketplace.orders(statuspending_contract) on the primary, recording the listing version, license template version, price and Toborlife fee. It also copies the set's current episode ids intomarketplace.order_episodes, so the order fixes exactly what this buyer gets, then starts the workflow. - Contract. Standard licenses are click-to-accept, generated from the license template. Custom or high-value deals go through a Dropbox Sign request signed by both parties. The signed PDF goes to the
contractsbucket under Object Lock; its SHA-256 fingerprint goes tomarketplace.contracts. - Payment. The marketplace payment provider charges the buyer and Toborlife holds the funds. The result is recorded in
marketplace.payments; the order becomespaid. - Access granted. The workflow writes
marketplace.entitlements, linking the buyer org to the order and its episodes. This is written to the primary, so access is live immediately. Noresource_access_grantsrow is created: that table only grants access inside a single org. - Export. The workflow starts the export packager with
app.current_orgset to the seller org. It reads the episode ids inmarketplace.order_episodes, fetches each episode's mp4 and parquet fromvideos, converts to the chosen format (LeRobot, HDF5), and adds a manifest and the license. The package is written toexportsand kept for the license term. An existing Toborlife customer can also import it into its own org as new episodes, running withapp.current_orgset to the buyer org. - Delivery. The buyer is emailed through SES and notified in the portal. Downloads use short-lived presigned URLs from IAM/STS; each download and SDK pull is logged.
- Acceptance window. The workflow waits about seven days.
- Payout. After the window, Toborlife pays the seller's share through the marketplace payment provider (price minus commission). The payout is recorded in
marketplace.payoutsand the order becomescomplete.
Every step writes to audit_logs, so admin can replay any order's history.
Flow 6: Admin operations¶
The admin console uses the same API with admin-only permissions.
- Set commission and featured listings.
- Remove listings or suspend accounts that break the rules.
- Watch dashboards for sales, failed jobs and payment problems; CloudWatch alerts the team when a worker fails, a job keeps retrying or payments start failing.