Creators

Validate a campaign spec (dry-run)

Validates a campaign spec exactly as create or update would and returns the normalized spec, the sentences that describe every rule-set, the sheet's alerts, and a previewHash to pass to the write — without writing anything. Pass id to dry-run an edit (the changes are merged into the campaign's current configuration and the changed sentences are listed), fromJobId to derive a draft from a job listing, or fromCampaignId to start from a copy.

post/campaigns/validate

Request

  • Base URL: https://viral.app/api/v1
  • URL: https://viral.app/api/v1/campaigns/validate
  • Auth: API key in header x-api-key

Request body

idstring

Dry-run an edit of this campaign instead of a new one.

fromJobIdstring

Derive the draft from a job listing's pay fields: cadence from its pay frequency, the weekly video minimum scaled to the cycle, amounts converted. The payout window is never derivable and comes back in missing.

fromCampaignIdstring

Start from a copy of an existing campaign: its spec with a new name and a fresh start date.

Example request

{
  "spec": {
    "name": "Creators Spain",
    "schedule": {
      "interval": "month",
      "anchor": "rolling"
    },
    "videoTarget": 30,
    "payouts": {
      "basePayouts": [
        {
          "perVideo": 10
        }
      ]
    }
  }
}

Response

OK

okboolean required

true when create or update would accept this spec as it is.

mode'create' | 'edit' required
previewHashstring

Hash of the normalized spec. Pass it to create or update to guarantee the campaign written is the one reviewed.

lockedFieldsstring[]
missingstring[]

Example response

{
  "spec": {
    "currency": "USD",
    "schedule": {
      "interval": "month",
      "intervalCount": 1,
      "anchor": "rolling",
      "startsOn": "2026-10-01",
      "timeZone": "UTC"
    },
    "videoTarget": 30,
    "videoTargetUnit": "videos",
    "briefId": "orgbrief_RwmraAffhMt9",
    "payouts": {
      "fixedSalary": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "basePayouts": [
        {
          "id": "rule_A1b2C3d4E5f6",
          "perVideo": 10,
          "steps": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "perVideo": 45
            }
          ],
          "minViews": 1000,
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "scope": "per_creative",
          "creatives": "once"
        }
      ],
      "cpmPayouts": [
        {
          "scope": "per_video",
          "creatives": "bestInWindow",
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "tiers": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "to": 100000,
              "rate": 1
            }
          ]
        }
      ],
      "flatBonuses": [
        {
          "scope": "per_video",
          "creatives": "bestInWindow",
          "mode": "highest",
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "tiers": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "to": 100000,
              "amount": 50
            }
          ]
        }
      ],
      "baseCap": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "performanceCap": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "eligibility": {
        "windowDays": 31,
        "publicationScope": "include_earlier"
      }
    }
  },
  "draft": {
    "currency": "USD",
    "schedule": {
      "interval": "month",
      "intervalCount": 1
    },
    "videoTargetUnit": "videos",
    "payouts": {
      "fixedSalary": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "basePayouts": [
        {
          "id": "rule_A1b2C3d4E5f6",
          "perVideo": 10,
          "steps": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "perVideo": 45
            }
          ],
          "minViews": 1000,
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "scope": "per_creative",
          "creatives": "once"
        }
      ],
      "cpmPayouts": [
        {
          "scope": "per_video",
          "creatives": "bestInWindow",
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "tiers": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "to": 100000,
              "rate": 1
            }
          ]
        }
      ],
      "flatBonuses": [
        {
          "scope": "per_video",
          "creatives": "bestInWindow",
          "mode": "highest",
          "platforms": [
            "tiktok",
            "instagram"
          ],
          "conditions": {
            "match": "all",
            "items": [
              {
                "field": "contentType",
                "operator": "is",
                "values": [
                  "slideshow"
                ]
              },
              {
                "field": "views",
                "operator": "atLeast",
                "value": 10000
              }
            ]
          },
          "tiers": [
            {
              "id": "rule_A1b2C3d4E5f6",
              "to": 100000,
              "amount": 50
            }
          ]
        }
      ],
      "baseCap": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "performanceCap": {
        "id": "rule_A1b2C3d4E5f6"
      },
      "eligibility": {
        "windowDays": 31,
        "publicationScope": "include_earlier"
      }
    }
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.