Partner Program
The platform's Partner Program as a connector's creator surface shows it — where a creator stands with the programme in the core's words, their referrals, commissions and payouts paged, their commitments with a proof sent and one added later, the payout rails and how they want to be paid, and the terms accepted.
Subscriby\Connector\Core\PartnerProgram. The Partner Program is the platform's, not a project's: a creator applies once from the dashboard, a person reads the application, and an approved partner holds a code, shares a link, earns a share of every invoice a creator they referred pays, climbs a ladder of points by promotion work the owner verifies, and is paid as Subscriby Credit or in cash. This port is a door to the same standing for a platform that has a conversation with creators. Every call takes the CreatorRef of the account that is talking and runs as that creator; the application itself stays the dashboard's, and a bot never re-implements a rule. Reads answer in words the core already phrased, and every refusal reaches you as PartnerRefused with a stable reason.
summaryFor()
$summary = $this->partners->summaryFor($creator);
$summary->standing; // PartnerStanding::None | Applied | Active | Rejected | Suspended
$summary->pitch; // the programme in one sentence
$summary->rateLabel; // "from 5% up to 30% of every invoice"
$summary->termsLines; // the terms as a partner is told them, one sentence a line
$summary->code; // the partner's code; null until approved
$summary->links; // list<PartnerLink>: "Web" first, then one per connector that registers creators
$summary->webLink(); // the web link, or null before approval
$summary->shareText; // a ready sentence with the web link, for a share button
$summary->ratePercent; // the rate today, whole percent
$summary->rateSentence; // "5% (5% base + 0 from commitments + 0 from paying referrals)"
$summary->nextTierSentence; // "+5 points at 10 paying referrals (you have 1)"
$summary->stats; // PartnerStats: clicks, referred, open, converted, underReview
$summary->balance; // PartnerBalanceSummary: earned, pending, payable, credited, paid, formatted
$summary->payoutMethodLabel; // "PayPal", or null until chosen
$summary->payoutDestination; // where the rail pays, in one line
$summary->termsAccepted; // whether the Partner Program Terms were accepted
$summary->attention; // PartnerAttention::Suspended | TermsNotAccepted | PayoutDetailsMissing, or null
$summary->appliedAt; // the application's date
$summary->rejectionReason; // why the owner turned it down, on a rejected one
$summary->reapplyAvailableAt; // when a rejected creator may apply againWhat is set depends on the standing: a creator who never applied reads the pitch and the terms alone, an applicant their application's date, a rejected one the reason and the date to apply again, an approved one everything. PartnerStanding::isApproved() is true for active and suspended partners alike; isEarning() for active ones only.
referrals(), rewards() and payouts()
$page = $this->partners->referrals($creator, page: 1, perPage: 5);
$page->items; // list<PartnerReferralRecord>
$page->page; // the page drawn
$page->lastPage; // the last page, at least 1
$page->total; // rows in all
$referral->creatorName; // the referred creator's display name, never their email
$referral->standingLabel; // "Converted"
$referral->outcome; // "Paid on Sep 30, 2026", "Window closes Apr 5, 2027", "Held for review by Subscriby"
$referral->earnsUntil; // when the commission window closes, once it earns
$referral->commissionPercent; // the rate locked on the referral, as the core stores it ("30.00")rewards() answers PartnerRewardRecords (the amount formatted, the kind, the standing, the moment such as "Payable Nov 9, 2026" and the note's sentence when a row was reversed or recalculated) and payouts() answers PartnerPayoutRecords (the amount, the rail, the date, the reference and the note). Every list is newest first and bounded at 50 rows a page.
commitments(), submitProof(), commitmentOptions(), audiencesFor() and addCommitment()
foreach ($this->partners->commitments($creator) as $commitment) {
$commitment->kindLabel; // "A long-form video review or tutorial (8 minutes or more)"
$commitment->standingLabel; // "Promised", "Verified", "Lapsed"
$commitment->points; // what it adds to the rate today
$commitment->maxPoints; // the most the kind can add
$commitment->moment; // "Proof due by Nov 19, 2026", "Verified Oct 4, 2026"
$commitment->audienceLabel; // "YouTube · https://www.youtube.com/@example"
$commitment->reachLabel; // "10,001 – 50,000"
$commitment->proofUrl; // the address sent, or null
$commitment->acceptsProof; // false once verified
}
$this->partners->submitProof($creator, $commitment->id, 'https://www.youtube.com/watch?v=…');
$options = $this->partners->commitmentOptions($creator);
$options->kinds; // list<PartnerCommitmentOption>: the kinds left to add, each with its channels
$options->reachBands; // list<PartnerReachOption>: the bands that earn anything, smallest first
$options->reachFloor; // the smallest band that counts, in words
$options->proofDays; // the days a commitment added today has to send its proof
$audiences = $this->partners->audiencesFor($creator, 'case_study'); // the declared audiences the kind fits
use Subscriby\Connector\Data\PartnerCommitmentDraft;
$this->partners->addCommitment($creator, new PartnerCommitmentDraft('case_study', audienceKey: $audiences[0]->key));
$this->partners->addCommitment($creator, new PartnerCommitmentDraft('short_form_video', channel: 'tiktok', url: 'https://www.tiktok.com/@…', reach: 'up_to_100k'));A proof tickets the core's support inbox; the rate moves only once the owner verifies the work. A commitment added later has its proof due proofDays from today, and the core refuses a kind already held (commitment_already_held), an audience the kind does not fit (commitment_audience_unfit) and one below the reach floor (commitment_audience_too_small). A verified commitment takes no proof (commitment_already_verified).
payoutOptions(), updatePayoutDetails() and acceptTerms()
$options = $this->partners->payoutOptions($creator);
foreach ($options->rails as $rail) {
$rail->value; // "paypal", "wise", "remitly", "crypto", "credit"
$rail->label; // "PayPal"
$rail->detailLabel; // "PayPal email", or null for a rail that needs none
$rail->needsSingleDetail; // one typed detail
$rail->paysToBankAccount; // a bank account, field by field
$rail->available; // false for Subscriby Credit until the rail is on
}
$options->minimumPayout; // "$50"
$options->settlementSentence; // how commissions are settled, in the core's words
$options->termsAccepted;
$options->termsUrl; // the public Partner Program Terms
use Subscriby\Connector\Data\PartnerBankDraft;
use Subscriby\Connector\Data\PartnerPayoutDraft;
$this->partners->updatePayoutDetails($creator, new PartnerPayoutDraft('paypal', detail: 'ada@example.com', legalName: 'Ada Lovelace', taxCountry: 'GB', usPerson: false, acceptTerms: true));
$this->partners->updatePayoutDetails($creator, new PartnerPayoutDraft('wise', legalName: 'Ada Lovelace', taxCountry: 'DE', usPerson: false, bank: new PartnerBankDraft('Ada Lovelace', 'Deutsche Bank', 'DE', 'DE89 3704 0044 0532 0130 00', 'COBADEFF')));
$this->partners->acceptTerms($creator);The terms come first: a draft saved before they were accepted is refused with terms_not_accepted unless it carries acceptTerms: true. A rail that needs a detail refuses without one (payout_details_missing), a rail that pays into a bank account refuses an incomplete one (bank_account_incomplete), and the credit rail refuses while it is off (credit_rail_off). Both calls answer the standing as it now reads.
Refusals
| Reason | When |
|---|---|
creator_unknown | the ref names no creator |
not_partner | the creator never applied |
not_approved | the application waits, was turned down, or the creator is suspended before any approval |
forbidden | the acting account may not run the write |
commitment_unknown | the id names none of the partner's commitments |
invalid_details | a kind, channel, band, rail, address or country code the programme cannot read |
| the core's own | terms_not_accepted, payout_details_missing, bank_account_incomplete, credit_rail_off, commitment_already_verified, commitment_already_held, commitment_audience_unfit, commitment_audience_too_small |
A deep link into the sign-up
An approved partner's links include one per connector that registers creators (t.me/<platform bot>?start=partner_<code> on Telegram). A conversation opened with such a link parks the code and hands it to Creators::register() as CreatorRegistration::$partnerCode; the core records the referral with source bot_deep_link, exactly as the web link's cookie records one, and an unknown or suspended code never stops the registration.
How is this guide?
Last updated on
Referral Management
A project's Referral Program as a connector's creator surface runs it — the options a setup needs, the programme in the core's words with its figures, the save from a draft, the pause, the resume and the delete, affiliates listed and read with their balances and payout details, approved, suspended and enrolled from a member search, and payouts recorded against what is payable.
Conformance Kit
The suite every connector passes before review — what "passes the kit" means, how it runs, how a rule fails, the report it returns, and the twenty-three rules grouped by what they check.