POST /sdk/v1/campaign-creators/:campaignCreatorRecordId/contract-history
Adds a contract version that becomes effective for media uploaded on or after the selected date. This is the same contract timeline used throughout Grade. All requests requireX-Application-Id and X-Api-Key.
Path parameter
campaignCreatorRecordId(required): the campaign creator whose contract you want to update.
Body
effectiveDate(required): a real date inYYYY-MM-DDformat.basedOnVersionId(required): theversionIdof the contract version that currently governseffectiveDate. Get it from Read campaign creator contract history. Send an explicit JSONnullonly when that response has an emptyhistoryand bothcurrentandnextScheduledarenull. This creates the first contract without guessing that the timeline is still empty.contract(required): the complete contract terms that should apply from that date.
To create a creator’s first contract, send the same complete contract shape
with
"basedOnVersionId": null. The server locks the creator record and
rejects the request with 409 CONTRACT_VERSION_STALE if another writer
creates a contract first.Contract fields
type(required):NONE,FIXED,PERFORMANCE,BONUS, orHYBRID. It must match the enabled payment sections.currency(required):USD,EUR,GBP,CAD,AUD,CHF,JPY,HKD,NZD,CNY,INR, orSGD.fixedPayment(required): a complete fixed-payment object, ornull.currency: the currency in which the fixed amount is authored.conversionPolicy:nullwhen this matchescontract.currency; otherwise it must beLEGACY_PAYMENT_REPOSITORY_FX.amount: payment amount.per:CREATORorPOST.calculation:STANDARD,PER_POST,SPLIT,PRORATED, orUPLOAD_THRESHOLD.- Also required:
upfrontPercentage,expectedPosts,minimumPosts,prorateByTime,platforms, andcrossposts. Usenull,false, or[]when a field does not apply. upfrontPercentageis non-null only forSPLIT;expectedPostsis non-null only forPRORATED;minimumPostsis non-null only forUPLOAD_THRESHOLD;crosspostsisEACH_POSTorONE_PAYMENT_PER_GROUPonly forPER_POST, and otherwise isnull.prorateByTimecan betrueonly forSTANDARD, andplatformsmust be empty whenperisCREATOR.
cpmPayment(required): a complete view-based payment object, ornull.- Required:
currency,conversionPolicy,rate,perViews,viewsFrom,minimumViews,maximumViews,excludeMinimumViews,maximumSpend,crossposts, andpays. Currency rules are the same as fixed payments. maximumSpendisnullor an object containingamount,per(CREATORorPOST), andperiod(LIFETIME,DAY,WEEK, orMONTH).crosspostsisEACH_POST,BEST_POST, orCOMBINE_POSTS.paysisCAMPAIGN_COMPLETION,NOW, orNOW_AND_STOP.
- Required:
bonusPayment(required): complete bonus rules, ornull.appliesTo:CREATOR,POST, orBEST_POST.pays:CAMPAIGN_COMPLETION,NOW, orNOW_AND_STOP. See bonus payout timing for when further tiers stop.rules:VIEWSrules and theirminimum/amounttiers. Every rule also requirescurrencyandconversionPolicyunder the same currency rules.VIEWSis the only supported metric.
crosspostRequirements(required):minimumPlatforms,requiredPlatforms, andcaptionContains, ornull.captionContains: a caption grouping override, ornullto disable it. Matching posts are grouped by the same local calendar day, using campaign timezone, then agency timezone, then UTC. This overrides the upload window and duration tolerance and permits multiple posts from the same platform. Read caption matching before using a hashtag shared by several videos. This differs from an account’s tracking filter.
recurringPayment(required):paymentsPerPeriod,period,weekday,dayOfMonth,startsImmediately,firstPaymentAt, andtimeZone, ornull.- Use
weekdayonly for weekly schedules anddayOfMonthonly for a once-monthly schedule.firstPaymentAtmust benullwhenstartsImmediatelyistrue; otherwise provide an ISO timestamp.
- Use
postsUploadedOnOrAfter(required): aYYYY-MM-DDeligibility date ornull.
Bonus payout timing
SetbonusPayment.pays to one of:
NOW_AND_STOP is the API value for Now, stop after payout in Grade. It
controls bonus eligibility; saving the contract does not initiate a payout.
For appliesTo: "POST", a payout closes the rule only for the paid post or
crosspost group. Other posts or groups remain eligible. For CREATOR and
BEST_POST, it closes the rule across the creator’s current contract instance,
including later uploads. Other bonus rules and manual bonuses are unaffected.
A pending approval or processing payout reserves that rule and scope against
another payout. If the reservation is released after cancellation or failure,
the scope becomes eligible again. After settlement, only a verified full
reversal of that payout reopens it; a partial reversal does not.
Existing payouts and older approvals retain the timing recorded when they
were created. Changing the contract to NOW_AND_STOP does not retroactively
close scopes paid under NOW.
Example request
Bonus tier amounts are totals, not increments. A post with 50,000 views in
the example above earns the 10,000-view tier amount of 50. With
NOW_AND_STOP, paying that bonus closes the rule for that post, so reaching
100,000 views later does not earn another bonus from that rule.Response
Successful creation returns201 with the public contract that was saved.
Safeguards
The endpoint applies the same contract-history safeguards as the Grade app. It will not add a version that changes protected paid or approved work, conflicts with another effective date, bypasses a pending payout approval, or changes a completed campaign where edits are not allowed. The server also checksbasedOnVersionId twice: once before validating the
contract and again in the transaction that writes it. For a first contract,
the explicit null assertion is also checked while the creator record is
locked. If the timeline changes between your read and write, the API returns
409 CONTRACT_VERSION_STALE.
Writing the same effectiveDate is allowed and replaces that date’s version
when basedOnVersionId identifies the existing same-date version and all
other safeguards pass.
Common errors
400 CONTRACT_VERSION_REQUIRED:basedOnVersionIdis omitted or invalid; it must be a governing version ID or explicitnullfor an empty timeline400: invalid date, incomplete contract, or unsupported contract terms401: missing or invalid SDK credentials404: campaign creator record not found409 CONTRACT_VERSION_STALE: the governing contract version changed; read history again before retrying409: no existing contract covers the effective date, or the change crosses a protected contract boundary