Skip to main content

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 require X-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 in YYYY-MM-DD format.
  • basedOnVersionId (required): the versionId of the contract version that currently governs effectiveDate. Get it from Read campaign creator contract history. Send an explicit JSON null only when that response has an empty history and both current and nextScheduled are null. 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.
The contract must be complete and explicit. Do not omit fields to imply a default or to inherit an earlier value. Start with the complete contract returned by the history GET, change the intended values, and send every field back. Use null, false, or [] explicitly where shown.
Grade-managed test-phase cutoffs, template identity, and internal history IDs are intentionally not writable through this public shape. Existing values are preserved from the governing unified version; for a first contract, test-phase guards are copied from the creator record. Payment amounts, source currencies, conversion behavior, eligibility dates, grouping, timing, and schedules are all explicit in the request and are never inferred from omitted fields.
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, or HYBRID. It must match the enabled payment sections.
  • currency (required): USD, EUR, GBP, CAD, AUD, CHF, JPY, HKD, NZD, CNY, INR, or SGD.
  • fixedPayment (required): a complete fixed-payment object, or null.
    • currency: the currency in which the fixed amount is authored.
    • conversionPolicy: null when this matches contract.currency; otherwise it must be LEGACY_PAYMENT_REPOSITORY_FX.
    • amount: payment amount.
    • per: CREATOR or POST.
    • calculation: STANDARD, PER_POST, SPLIT, PRORATED, or UPLOAD_THRESHOLD.
    • Also required: upfrontPercentage, expectedPosts, minimumPosts, prorateByTime, platforms, and crossposts. Use null, false, or [] when a field does not apply.
    • upfrontPercentage is non-null only for SPLIT; expectedPosts is non-null only for PRORATED; minimumPosts is non-null only for UPLOAD_THRESHOLD; crossposts is EACH_POST or ONE_PAYMENT_PER_GROUP only for PER_POST, and otherwise is null. prorateByTime can be true only for STANDARD, and platforms must be empty when per is CREATOR.
  • cpmPayment (required): a complete view-based payment object, or null.
    • Required: currency, conversionPolicy, rate, perViews, viewsFrom, minimumViews, maximumViews, excludeMinimumViews, maximumSpend, crossposts, and pays. Currency rules are the same as fixed payments.
    • maximumSpend is null or an object containing amount, per (CREATOR or POST), and period (LIFETIME, DAY, WEEK, or MONTH).
    • crossposts is EACH_POST, BEST_POST, or COMBINE_POSTS. pays is CAMPAIGN_COMPLETION, NOW, or NOW_AND_STOP.
  • bonusPayment (required): complete bonus rules, or null.
    • appliesTo: CREATOR, POST, or BEST_POST.
    • pays: CAMPAIGN_COMPLETION, NOW, or NOW_AND_STOP. See bonus payout timing for when further tiers stop.
    • rules: VIEWS rules and their minimum/amount tiers. Every rule also requires currency and conversionPolicy under the same currency rules. VIEWS is the only supported metric.
  • crosspostRequirements (required): minimumPlatforms, requiredPlatforms, and captionContains, or null.
    • captionContains: a caption grouping override, or null to 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, and timeZone, or null.
    • Use weekday only for weekly schedules and dayOfMonth only for a once-monthly schedule. firstPaymentAt must be null when startsImmediately is true; otherwise provide an ISO timestamp.
  • postsUploadedOnOrAfter (required): a YYYY-MM-DD eligibility date or null.

Bonus payout timing

Set bonusPayment.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 returns 201 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 checks basedOnVersionId 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: basedOnVersionId is omitted or invalid; it must be a governing version ID or explicit null for an empty timeline
  • 400: invalid date, incomplete contract, or unsupported contract terms
  • 401: missing or invalid SDK credentials
  • 404: campaign creator record not found
  • 409 CONTRACT_VERSION_STALE: the governing contract version changed; read history again before retrying
  • 409: no existing contract covers the effective date, or the change crosses a protected contract boundary
Read the updated timeline with Read campaign creator contract history.