---
title: "Create a new job"
method: POST
path: "/jobs"
tags: ["Creators"]
---

# Create a new job

`POST /jobs`

## Request

- Base URL: `https://viral.app/api/v1`
- URL: `https://viral.app/api/v1/jobs`
- Auth: API key in header `x-api-key`

Creates a discovery job posting as a draft with product, requirements, application challenge, and payment configuration. The body and the application challenge are written as markdown (bodyMarkdown, challengeBriefMarkdown) or TipTap JSON (body, challengeBrief); reads return both.

## Request body

- object: Request to create a new discovery job posting (created as draft)
  - `productTitle` string, required: Product the job promotes
  - `productDescription` string, required: Short product description shown in the listing
  - `logoUrl` string: Template URL of the uploaded product logo
  - `productNiches` string[], required: Product niches (shared taxonomy with creator discovery profiles)
  - `contentFormats` string[]: Content formats the job asks for; empty accepts any
  - `countryResidences` string[]: Countries of residence creators may apply from (ISO3); empty accepts any
  - `languages` string[]: Content languages the creator must produce in; empty accepts any
  - `minAge` integer: Minimum creator age (no maximum age by design)
  - `aiContentPolicy` 'real_only' | 'ai_only': AI content requirement — 'real_only' excludes fully-AI creators, 'ai_only' excludes real-only creators; unset accepts both
  - `jobType` 'canvas_ugc' | 'influencer' | 'ugc_ads' | 'creator_manager' | 'other', required
  - `minWeeklyHours` integer: Minimum weekly hours the creator must have available
  - `minWeeklyVideos` integer: Minimum videos per week the creator must be able to produce
  - `platformFocus` string[]: Platforms the content is produced for
  - `accountType` 'new_account' | 'personal_account' | 'company_account'
  - `exampleVideoUrls` string[]: Example video links (TikTok, Instagram Reels, YouTube); each becomes an example-video tile on the posting at save time, tracked as a reference — a link that cannot be fetched stays a plain link. Ignored when exampleVideos is sent.
  - `exampleVideos` object[]: Ordered example videos shown on the listing
    - `orgAccountId` string, required: Organization account ID with orgacc_ prefix. Not the same as platform account ID.
    - `platform` 'facebook' | 'instagram' | 'tiktok' | 'youtube' | 'snapchat', required: Social media platform (facebook, instagram, tiktok, youtube, snapchat)
    - `platformVideoId` string, required
    - `url` string, uri, required
    - `label` string, nullable: Optional caption creators see above the video, after its number in the list
  - `videoSubmissionRequired` boolean
  - `challengeBrief` object, nullable: The application challenge as TipTap JSON. Send this or challengeBriefMarkdown.
    - `type` 'doc', required
    - `content` object[]
      - `type` string, required
  - `challengeBriefMarkdown` string, nullable: Markdown: `##`/`###` headings, paragraphs, **bold**, *italic*, [links](https://…), images ![alt](https://…), `- ` and `1. ` lists, and `$variable` placeholders. Code, quotes, rules and tables fall back to plain paragraphs.
  - `sampleVideos` object[]: Ordered sample videos of the application challenge
    - `orgAccountId` string, required: Organization account ID with orgacc_ prefix. Not the same as platform account ID.
    - `platform` 'facebook' | 'instagram' | 'tiktok' | 'youtube' | 'snapchat', required: Social media platform (facebook, instagram, tiktok, youtube, snapchat)
    - `platformVideoId` string, required
    - `url` string, uri, required
    - `label` string, nullable: Optional caption creators see above the video, after its number in the list
  - `currency` 'USD' | 'EUR' | 'CHF' | 'GBP' | 'CNY' | 'JPY' | 'KRW' | 'THB' | 'IDR' | 'VND' | 'RUB', required
  - `payFrequency` 'one_time' | 'per_day' | 'per_week' | 'per_month', required
  - `flatSalaryAmount` integer: Amount in minor units of the job currency
  - `perVideoAmount` integer: Amount in minor units of the job currency
  - `cpmAmount` integer: Amount in minor units of the job currency
  - `bonusAmount` integer: The HIGHEST one-time bonus a single video can earn, in minor units of the job currency (creators read it as 'Bonus up to …'). The view milestones are campaign terms; a rate per 1,000 views is cpmAmount, never a bonus.
  - `body` object, nullable: The creator-facing posting as TipTap JSON. Send this or bodyMarkdown.
    - `type` 'doc', required
    - `content` object[]
      - `type` string, required
  - `bodyMarkdown` string, nullable: Markdown: `##`/`###` headings, paragraphs, **bold**, *italic*, [links](https://…), images ![alt](https://…), `- ` and `1. ` lists, and `$variable` placeholders. Code, quotes, rules and tables fall back to plain paragraphs.

## Response `200`

OK

- object: Created job posting with all database fields and generated ID
  - `id` string, required
  - `status` 'draft' | 'public' | 'paused', required
  - `productTitle` string, required
  - `productDescription` string, required
  - `logoUrl` string, nullable, required
  - `productNiches` string[], required
  - `contentFormats` string[], required
  - `countryResidences` string[], required
  - `languages` string[], required
  - `minAge` integer, nullable, required
  - `aiContentPolicy` string, nullable, required
  - `jobType` string, required
  - `minWeeklyHours` integer, nullable, required
  - `minWeeklyVideos` integer, nullable, required
  - `platformFocus` string[], required
  - `accountType` string, nullable, required
  - `exampleVideoUrls` string[], required
  - `videoSubmissionRequired` boolean, required
  - `challengeBrief` union, required
    - string
    - number
    - boolean
    - object
    - unknown[]
      - unknown
  - `sampleVideoUrls` string[], required
  - `currency` string, required
  - `payFrequency` string, required
  - `flatSalaryAmount` integer, nullable, required
  - `perVideoAmount` integer, nullable, required
  - `cpmAmount` integer, nullable, required
  - `bonusAmount` integer, nullable, required
  - `body` union, required
    - string
    - number
    - boolean
    - object
    - unknown[]
      - unknown
  - `publishedAt` string, date-time, nullable, required
  - `embedding` unknown
  - `embeddingModel` string, nullable, required
  - `embeddedAt` string, date-time, nullable, required
  - `firstMatchesNotifiedAt` string, date-time, nullable, required
  - `pausedReason` string, nullable, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `actorType` 'user' | 'system' | 'api_token', required
  - `userId` string, required
  - `orgId` string, required
  - `bodyMarkdown` string, nullable, required: The posting's body as markdown; null without a body
  - `challengeBriefMarkdown` string, nullable, required: The application challenge as markdown; null without one

## Other responses

- `400`: 400
- `401`: 401
- `402`: 402
- `404`: 404
- `408`: 408
- `429`: 429
- `500`: 500

---

[API](https://skmtc.dev/viral/apis/viral-app-api.md) · [All operations](https://skmtc.dev/viral/apis/viral-app-api/llms.txt) · [OpenAPI document](https://skmtc.dev/viral/apis/viral-app-api/revisions/31e97fa79ef1?raw)
