ManyVids Clone Script: Selling Content Item by Item

Live-auction listing for exclusive creator video content with starting bid, creator identity, and real-time bidding access

Table of Contents

Key Takeaways

  • A ManyVids clone script sells content item by item through one small ledger table, pay_per_views, holding the buyer, a polymorphic pointer to the item, the price paid and a status. Everything downstream follows from how thin that row is.
  • The documented unlock row has no expiry column, so an unlock is permanent by shape and re-checked by lookup on each render rather than cached as an entitlement.
  • Because the unlock row stores its own price, repricing an item later does not rewrite what past buyers paid. Deletion is undefined: the schema reference documents no soft delete on the posts table.
  • Refunds are representable on the money ledger but not on the unlock record, whose statuses stop at pending, completed and failed. A refunded buyer keeping access is a decision you make in code.
  • Purchased media sits behind private buckets and signed URLs in the architecture docs, but the entitlement test on those URLs is written up as hardening work to maintain, not a certified control.
  • Four per-item claims have no column behind them: priced stories, a price field on reels, a generic custom-content request record, and an immutable financial audit log.

Where does the price of a single item actually live?

Per-item selling is the opposite shape to recurring revenue: one buyer, one item, one price, one payment, and a permanent claim afterwards. No renewal to lean on, no period to expire. The platform has to remember, correctly and forever, that this person bought that thing.

If you are evaluating a ManyVids clone as the base for a per-item catalog, the first move is not reading the feature list. It is opening the schema and asking where a price can be written. In the MXFans documentation set behind this product family, prices for individual items sit across several tables rather than one priced-item entity.

Four locations carry real columns. A feed post has updates.is_paid, updates.price and updates.locked, the last an enum of yes and no rather than a boolean. A direct message has messages.price and messages.is_paid. A vault has vaults.access_price, priced at the container and not the file. A shoutout booking carries a price in three places: users.shoutout_price as the creator default, shoutout_offerings.price as the catalog price, and shoutout_requests.price captured on the individual request.

That last pattern, a price copied onto the record of the thing bought, is the one you want everywhere. It makes a historical sale readable a year later. The feed post does not follow it on its own, because updates.price is a single mutable column on the item. Which is why the unlock record matters.

Creator settings for weekly, monthly, three-month, six-month, and annual subscription prices and availability
Image Source: Miracuves product screenshot.

What does a purchase actually write?

One table carries the entitlement. The schema documents pay_per_views with six columns: id, user_id as the buyer, payable_id and payable_type as a polymorphic pointer to what was bought, price as the amount paid, and status defaulting to completed with pending and failed as the other documented values. The payable type is documented as covering updates, media and reels, and the entity-relationship document describes the same table as monetizing both content and messages.

The money lands separately. The schema calls transactions the hub and lists its statuses as pending, completed, failed, cancelled and refunded, with its types including a dedicated ppv entry alongside subscription, tip, purchase, withdrawal, refund, gift and shoutout. A per-item sale therefore produces two rows: an entitlement row and a money row.

Here is the detail founders miss. The transactions table carries typed foreign keys for three relations: subscription_id, withdrawal_id and purchase_id. There is no pay_per_view_id. Product purchases get a typed link back to their money row; content unlocks do not. The documented path between an unlock and the payment that caused it is the generic reference string, which the technical dossier describes as a loose pointer to a subscription id, a post id or similar. When finance reconciles a disputed unlock against a gateway charge, that is the join you will wish had been a foreign key.

Two further absences matter. The documented columns include no created timestamp, so the only clock on a per-item sale is the one on the transaction. And the schema appendix describes the table’s keys as two foreign keys on user plus the polymorphic pair, with no unique constraint across buyer and item. Nothing prevents two unlock rows for the same buyer and item, which is what a double-tapped buy button produces.

Is an unlock permanent, or re-checked on every view?

Both, and the distinction matters. The unlock row has no expiry, no valid-until and no revoked flag among its documented columns, so by shape it is permanent. The feature catalog describes the pay-per-view module’s monetization in one word, one-time, and its access matrix grants a buyer locked content for purchased items only.

Permanence in the data is not a cached entitlement in the application. No documented column on the item records who has unlocked it, so the gate on every locked render is a lookup into pay_per_views for this buyer and this polymorphic pair. The schema’s own content-locking narrative complicates this: it states that media.is_paid is populated on payment, while the media table definition in the same document lists no is_paid column. One of those statements is stale, and until you read the code you do not know whether the gate consults the ledger or a per-media flag.

There is a second gap around that lookup. The schema’s recommended index block covers user lookups, content feeds, financial queries and messaging, and lists no index on pay_per_views at all. For a catalog whose core read is an entitlement check on a polymorphic pair, a composite index across buyer, payable type and payable id is the first addition, and it is not in the documented set.

One more thing to settle. The feature catalog’s fan access matrix shows a paid subscriber able to view locked content too, not only the per-item buyer, so the entitlement check is not purely the unlock ledger. Decide deliberately which relationships open a priced item.

What happens if the creator deletes or reprices a purchased item?

Repricing is the good news. Because pay_per_views.price stores the amount actually paid rather than reading through to the item, a creator changing updates.price later does not rewrite history. Past sales stay readable at the price they happened. That is a genuine property of the documented design, and the reason the unlock row should never be reduced to a join table of buyer and item.

Deletion is where the documentation runs out. The schema’s soft-delete section names exactly three patterns: a separate history table for cancelled subscriptions, a deleted timestamp on messages, and a status field on reports. The posts table is not among them, and its definition in the schema reference lists no deleted timestamp. The technical dossier’s illustrative DDL for the same entity does include one. Two documents, two shapes, and no stated behaviour for the case a per-item business hits constantly: a creator removes an item people paid for.

Nothing documented describes what the buyer sees afterwards. The unlock row survives, because it points at an id rather than depending on the row. Whether the buyer gets the content, an empty state or an error depends on code you have not read. Put that question to an implementation team before you commit, then own the policy: either items with sales become archivable rather than deletable, or deletion destroys something a buyer paid for and you refund accordingly.

Can a buyer be refunded, and what does that do to the unlock?

A refund exists on the money side. The transaction type list includes refund, the status list includes refunded, and the feature catalog records manual refund initiation with a reason, dispute and chargeback management, and gateway reconciliation as admin capabilities. The technical dossier shows a refund method on the payment provider interface and a scheduled refund-processing job.

The unlock record does not follow. Its documented statuses are pending, completed and failed: no refunded value, no revoked value. Contrast the product purchase record, documented as pending, completed or refunded, which means the shop side can express a reversed sale on the order itself and the content side cannot.

So: refunding a content unlock moves money and leaves the entitlement intact unless you write the logic that takes it back. That is not necessarily wrong; many per-item businesses let a refunded buyer keep access on small amounts. What is wrong is not deciding. If a refund revokes, put the state on the unlock row rather than inferring it from the ledger, because inferring it means the gate joins to transactions on every locked render.

Is purchased media access-controlled, or only unlisted?

This question decides whether your paywall is real, because the first buyer of any popular item will post the URL somewhere.

The architecture documents answer it at the storage layer. The storage design lists buckets with explicit access postures: raw uploads and transcoded content are private and served through signed URLs, message attachments are private and ephemeral, and only avatars and the CDN layer are public. The implementation notes show temporary signed URL generation with a thirty-minute window and signed CDN URLs for premium content. The API catalog backs this at route level: the vault download endpoint is annotated as requiring a purchase or access check, and the completed shoutout download is restricted to an authorized buyer.

Do not read that as a finished, verified control. The security assurance document lists public object storage exposure in its residual risk register at high severity, with private buckets, signed URLs and entitlement checks as the mitigation. Its threat model names unauthorized pay-per-view unlocks explicitly as business-logic abuse, countered by entitlement checks, transaction status verification and audit logs. Its readiness summary makes maintaining strict owner and entitlement tests across media, invoices, messages and paid content the second-highest-value hardening item. The pattern is documented; the enforcement is work to keep doing. Budget for an entitlement test suite over every media-serving route.

Do custom orders have a state machine, or just a request record?

One of them does. The shoutout booking is the best-documented per-item order in the platform and the model to copy for anything bespoke. The shoutout_requests table carries a requester, a creator, a recipient name, free-text instructions, a price, a separate paid flag, a creator response, a delivered video path, a delivered_at timestamp, and a status documented as pending, accepted, rejected and completed. The catalog side carries shoutout_offerings with a price, a description and delivery_days as a stated service level. The API catalog gives it real routes: received and sent lists, an offerings lookup, a deliver action scoped to creator or manager, and a buyer-scoped download.

That is a genuine four-state machine with payment and fulfilment tracked separately, which is right for work bought before it exists. Note what it lacks: no cancelled, expired or refunded state. A creator who accepts and never delivers leaves a request sitting in accepted with money collected and the delivery_days promise unenforced. The service level is stored; nothing documented acts on it, so the job that ages out overdue requests is yours to write.

A generic custom content request is weaker. The requirements document lists it as an included fan-initiated custom order flow and the feature catalog as commission-based custom content, but no custom request table exists anywhere in the schema’s complete model catalog. The nearest records are the shoutout request above and a custom-content type inside the shop catalog, a different surface with its own order record. If your pitch is bespoke commissions beyond shoutouts, you are building that state machine, not configuring one.

The table below is the feature list a founder actually needs: per surface, the price column, what a purchase writes, and what the docs leave open.

Per-item surfaceDocumented price columnWhat a purchase writesWhat you must settle yourself
Individually priced feed postupdates.price, with updates.is_paid and updates.lockedpay_per_views row with payable type updates, plus a transactions row of type ppvNo unique constraint across buyer and item; no typed link from unlock to transaction; no documented soft delete on the item
Priced message attachmentmessages.price, with messages.is_paidUnlock ledger covers messages per the ERD; files live in media_messagesWhether the unlock addresses the message or each attached file; messages carry a deleted timestamp while the unlock has no revoked state
ReelNone documented on reelspay_per_views.payable_type explicitly lists reelsThe price field itself, and the lock flag, before a reel can be sold at all
StoryNone documented on storiesNothing; stories are not among the documented payable typesThe entire path, despite the module matrix listing stories as pay-per-view monetized
Vault accessvaults.access_price, priced per containerDownload route is annotated as purchase or access checkedPer-file pricing, and which ledger row records a vault entitlement
Shoutout bookingshoutout_offerings.price and users.shoutout_price, copied to shoutout_requests.priceshoutout_requests row with status, paid flag and delivered_atCancelled, expired and refunded states; enforcement of the stored delivery_days promise

Which per-item claims have no table behind them?

Priced stories. The module matrix lists the stories module with pay-per-view as its monetization column. The stories table documents a caption, background, font reference, type, view count and expiry, and no price or lock column. The unlock ledger’s documented payable types are updates, media and reels. Stories are absent from both sides of the mechanism.

A reel price. The same matrix lists reels under pay-per-view and the ledger genuinely names reels as a payable type, but the reels table documents no price. The ledger can record the sale of something whose price has nowhere to live.

An immutable financial audit log. The admin feature table records one, described as an immutable log of all financial actions. The schema’s complete model catalog, enumerating every table across identity, content, commerce, messaging, live, AI, analytics, settings, advertising and system, contains no audit log table. Audit logging appears in the security documents as a control to verify, which is the language of a recommendation. An append-only record of who changed a price, deleted an item or issued a refund is build work to scope.

A generic custom-order record, covered above. None of this makes the platform a poor foundation; the gap report shipped alongside these documents records what the suite does not cover. Plan around the gaps rather than discover them in month three.

How do you report revenue on a per-item catalog?

A catalog business reports per item, not per fan. The documented rollups get you partway: post_stats_daily carries a ppv_unlocks counter per post per day alongside views, likes, comments and shares. That is the per-item conversion signal and it is useful. What it does not carry is revenue. The companion user_stats_daily table has a single daily earnings column and a separate tips column, so earnings are not broken out by source. No per-item revenue column exists in the rollups.

Per-item revenue therefore has to be aggregated from raw rows, and this is where the missing timestamp on the unlock ledger bites: you will group transactions by date and resolve them back to items through the generic reference string rather than summing priced unlock rows by day. Two additions make that reporting cheap instead of painful. Put a created timestamp on the unlock row, and put the fee split on the money row.

The second matters most. The platform fee is configurable globally and per creator, via an admin setting and a users.custom_fee override. The schema’s transactions table records an amount and no split; the technical dossier’s illustrative DDL for the same table records platform_fee and creator_earnings as stored columns. If the shipped table follows the schema reference, every historical sale has its split recomputed from today’s fee setting, and a per-creator fee changed last quarter silently rewrites last quarter’s earnings. Store the split at the moment of sale.

Creator sales dashboard listing buyers, products, delivery status, price, coupons, dates, and fulfillment actions
Image Source: Miracuves product screenshot.

What does the operator wire up rather than inherit?

Payments are integrations. The documentation marks payment gateway settings as operator-configurable and treats gateway credentials as deployment secrets. The schema carries a payment_gateways configuration table and native columns on the user record for several providers, and buyers can pay directly or from a pre-funded wallet, with users.wallet as the spending balance and users.balance as the creator earnings balance. The plumbing is there; the merchant relationships are yours, and for small, frequent, high-dispute sales they are the harder half.

Video encoding is a named third-party dependency. The documents name Coconut alongside FFmpeg for asynchronous encoding driven by webhooks per media type across posts, messages, stories, reels and vault items, and the security handbook lists a Coconut API key and webhook secret among the environment variables. That is an account you hold, and the webhook marking a purchased video ready is the one to test hardest: a buyer who pays before transcoding finishes is a paywall that took money and showed nothing.

Identity and age assurance are schema support plus provider work. The documentation records an age verification flag on the user record and separate verification request tables for individual and business creators, and describes GDPR readiness as requiring application logic. Tax rates need external rules or a service, and platform-wide refund terms are an admin-configurable text field, not an engine. Policy and compliance obligations for this category sit with you as the operator regardless of what the software provides.

Security hardening is mixed, and the documents are clear about it. Token authentication, two-factor enrolment fields and a two-factor code table, throttling middleware and account status gates are present in the implementation documentation. But incomplete rate limiting sits in the residual risk register at medium severity with per-flow throttles and firewall controls as the mitigation, and audit logging appears as a control to verify rather than a shipped table. Read those as a to-do list with a head start.

Founder Decision Signals

Catalog depth comes first. Per-item selling rewards a back catalog that keeps earning. If your creators post a handful of items a month, the unlock ledger stays sparse.

Dispute volume comes second. Individual sales generate individual complaints, and the three gaps that matter most cluster around disputes: no refunded state on the unlock, no typed link from unlock to payment, and no audit log table. If your market or your processor makes disputes frequent, close those three before launch.

Item lifetime comes third. If creators routinely take content down, you need a deletion policy and an archival state before your first thousand sales.

Price range comes fourth. The admin panel supports minimum and maximum price limits per pay-per-view post, which is the right control. Low prices make a duplicate unlock cheap; high prices make the unique constraint and the stored fee split non-optional.

Bespoke share comes last. If commissioned work is a real revenue line, you are adopting the shoutout state machine and extending it, and that deserves its own sprint rather than a checkbox on a creator economy launch plan.

Common Pay-Per-Item Catalog Mistakes to Avoid

Treating the unlock ledger as a join table. The price on the unlock row is what makes a sale historically readable. Normalize it away and read through to the item instead, and every reprice silently rewrites your history. Keep the copy.

Shipping without a unique constraint. Buyer plus payable type plus payable id, unique. One migration, and it prevents the most common per-item support ticket: a buyer charged twice by an impatient second tap on a slow connection.

Assuming unlisted equals protected. If a purchased file can be fetched without an entitlement check because the URL leaked, you do not have a paywall. The private-bucket and signed-URL pattern is documented; the test proving it holds on every route is yours.

Reporting from rollups alone. The per-post unlock counter is a conversion metric, not a revenue metric. Creators will ask what an item earned, and that answer needs priced rows with a stored fee split, which makes the two additions above prerequisites rather than improvements.

How a Ready-Made Foundation Fits a Per-Item Catalog

The argument for a built foundation is not that it saves the entitlement work. It is that the entitlement work is the only part worth your attention, and a foundation hands you the rest assembled: accounts and roles, a media pipeline with asynchronous encoding and private storage, a central financial ledger, a messaging layer, a moderation queue, creator verification, payout flows, and an admin panel with price limits and fee configuration.

What you spend engineering on instead is the short list this article has been building. A unique constraint and a created timestamp on the unlock row. A typed foreign key from the unlock to its transaction. A stored fee split on the money row. A refund state on the unlock, and an admin action that sets it. A deletion and archival policy for items with sales. An entitlement test suite over every media-serving route. An append-only log of price changes, deletions and refunds. A price column wherever you intend to sell a surface the schema does not price yet. That is focused, estimable work, and it is what makes a per-item catalog trustworthy.

This is where Miracuves is useful. We ship the foundation with its documentation open, including the gap report listing what the suite does not cover, so the conversation starts from the tables rather than a feature grid. For a per-item catalog we walk the unlock ledger with your engineers, agree which entitlement decisions are policy and which are code, and scope the migrations before go-live. The per-item build is on the ManyVids clone script page, and the wider platform under our influencer platform solutions. If the money leaving side is what you are least sure about, our breakdown of creator payout options covers the other end of the same ledger.

Final Thoughts

Selling content item by item looks like the simpler model. One payment, one item, no renewals, no proration, no dunning. In the data it is the stricter one, because a subscription forgives you: it expires and re-bills, giving you another chance every month. A per-item sale gives you one chance to write a durable claim, and that claim has to survive repricing, deletion, refunds, disputes and a buyer who returns two years later.

Everything above came from one small table and the honest question of what its row does and does not guarantee. That is the right first question for any platform, and the answer should be specific: these columns exist, this constraint does not, this behaviour is undefined. Build the ledger deliberately, because it is the only record that a stranger trusted you with money for a file.

FAQs

<!– wp:rank-math/faq-block {"questions":[{"id":"faq-question-17613401","title":"What table records a pay-per-item content purchase?","content":"

The documented table is pay_per_views: the buyer, a polymorphic pointer of payable_id and payable_type, the price paid, and a status defaulting to completed. The money lands separately in the central transactions ledger, which carries a dedicated ppv type.

“,”visible”:true},{“id”:”faq-question-17613402″,”title”:”Is a content unlock permanent or does it expire?”,”content”:”

Permanent by shape. The unlock row has no expiry, valid-until or revoked column, and the feature catalog calls pay-per-view one-time. With no entitlement cache documented on the item, the gate is a ledger lookup on every render, and the schema’s recommended index list covers no index on that table.

“,”visible”:true},{“id”:”faq-question-17613403″,”title”:”If a creator reprices an item, does it change what past buyers paid?”,”content”:”

No. The unlock row stores its own price, recording what was actually paid rather than reading through to the item’s current price. Repricing later does not rewrite historical sales, which is one of the genuinely well-designed properties of this model.

“,”visible”:true},{“id”:”faq-question-17613404″,”title”:”What happens to an unlock if the creator deletes the purchased item?”,”content”:”

The documentation does not define it. The schema reference lists soft deletes for only three patterns and the posts table is not one of them, while a separate architecture document shows a deleted timestamp on the same entity. The unlock row survives, but what the buyer sees is application behaviour you must specify. The safer policy is to make items with sales archivable rather than deletable.

“,”visible”:true},{“id”:”faq-question-17613405″,”title”:”Can a content unlock be refunded?”,”content”:”

The money can be. Transactions support a refund type and a refunded status, and admin tooling covers manual refunds with a reason plus chargeback handling. The unlock does not follow: its statuses stop at pending, completed and failed. Whether a refunded buyer keeps access is logic you write, and the state belongs on the unlock row rather than being inferred from the ledger.

“,”visible”:true},{“id”:”faq-question-17613406″,”title”:”Is purchased media properly access-controlled?”,”content”:”

The architecture documents describe private buckets with signed URLs on a thirty-minute window, ephemeral message attachments, and route-level purchase or access checks on vault and shoutout downloads. But the security assurance document lists public object storage exposure in its residual risk register and treats strict entitlement tests across paid content as hardening work. Verify the enforcement yourself rather than inheriting the claim.

“,”visible”:true},{“id”:”faq-question-17613407″,”title”:”Do bespoke or custom orders come with a workflow?”,”content”:”

Shoutout bookings do: instructions, a copied price, a separate paid flag, a creator response, a delivered timestamp, and a four-state status of pending, accepted, rejected and completed, with routes for delivery and buyer download. There is no cancelled, expired or refunded state, and the stored delivery-days promise is unenforced. A generic custom content request appears in the feature lists but has no table in the schema’s model catalog.

“,”visible”:true},{“id”:”faq-question-17613408″,”title”:”What should a founder add before launching a per-item catalog?”,”content”:”

A unique constraint across buyer and item, a created timestamp on the unlock row, a typed foreign key from unlock to transaction, the fee split stored at the moment of sale, a refund state with an admin action behind it, an archival policy for sold items, entitlement tests on every media-serving route, and an append-only log of price changes, deletions and refunds. Miracuves scopes these migrations with your team before go-live rather than after the first dispute.

“,”visible”:true}]} –>

What table records a pay-per-item content purchase?

The documented table is pay_per_views: the buyer, a polymorphic pointer of payable_id and payable_type, the price paid, and a status defaulting to completed. The money lands separately in the central transactions ledger, which carries a dedicated ppv type.

Is a content unlock permanent or does it expire?

Permanent by shape. The unlock row has no expiry, valid-until or revoked column, and the feature catalog calls pay-per-view one-time. With no entitlement cache documented on the item, the gate is a ledger lookup on every render, and the schema’s recommended index list covers no index on that table.

If a creator reprices an item, does it change what past buyers paid?

No. The unlock row stores its own price, recording what was actually paid rather than reading through to the item’s current price. Repricing later does not rewrite historical sales, which is one of the genuinely well-designed properties of this model.

What happens to an unlock if the creator deletes the purchased item?

The documentation does not define it. The schema reference lists soft deletes for only three patterns and the posts table is not one of them, while a separate architecture document shows a deleted timestamp on the same entity. The unlock row survives, but what the buyer sees is application behaviour you must specify. The safer policy is to make items with sales archivable rather than deletable.

Can a content unlock be refunded?

The money can be. Transactions support a refund type and a refunded status, and admin tooling covers manual refunds with a reason plus chargeback handling. The unlock does not follow: its statuses stop at pending, completed and failed. Whether a refunded buyer keeps access is logic you write, and the state belongs on the unlock row rather than being inferred from the ledger.

Is purchased media properly access-controlled?

The architecture documents describe private buckets with signed URLs on a thirty-minute window, ephemeral message attachments, and route-level purchase or access checks on vault and shoutout downloads. But the security assurance document lists public object storage exposure in its residual risk register and treats strict entitlement tests across paid content as hardening work. Verify the enforcement yourself rather than inheriting the claim.

Do bespoke or custom orders come with a workflow?

Shoutout bookings do: instructions, a copied price, a separate paid flag, a creator response, a delivered timestamp, and a four-state status of pending, accepted, rejected and completed, with routes for delivery and buyer download. There is no cancelled, expired or refunded state, and the stored delivery-days promise is unenforced. A generic custom content request appears in the feature lists but has no table in the schema’s model catalog.

What should a founder add before launching a per-item catalog?

A unique constraint across buyer and item, a created timestamp on the unlock row, a typed foreign key from unlock to transaction, the fee split stored at the moment of sale, a refund state with an admin action behind it, an archival policy for sold items, entitlement tests on every media-serving route, and an append-only log of price changes, deletions and refunds. Miracuves scopes these migrations with your team before go-live rather than after the first dispute.

Disclaimer

Miracuves is an independent software development company. We are not affiliated with, connected to, sponsored by, or endorsed by any company or product named in this article.

Why this name

Terms such as “X Clone” are used descriptively. It is how the software industry refers to building a platform with functionality comparable to a known service, and how clients search for it.

Who built this

The entire design and codebase of our products is built by our own team. Our products contain no code, design, graphics, or content originating from any third-party website or applications.

Trademarks

All third-party names and marks referenced in this article are the property of their respective owners, referenced solely to identify the services discussed.

Connect

This field is for validation purposes and should be left unchanged.
Your Name(Required)