vlayervlayer docs
API reference

Campaigns

Create a campaign and its challenge from a public Instagram or TikTok post URL, then list, summarise, end or delete it.

List campaigns

Lists active campaigns, newest first, with the caller's own attempt on each.

A row is not the create response reshaped: the campaign is flattened, brandName and brandLogoUrl are joined in, challenge is trimmed to id, platform, contentType, canonicalUrl and instructionText, and myAttempt carries the calling token's attempt on that challenge or null. There is no isActive, because only active campaigns are listed — use GET /campaigns/{id} to read one that has ended.

GET
/campaigns

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Query Parameters

pageinteger
Default: 1Minimum: 1
limitinteger
Default: 20Minimum: 1Maximum: 100
curl -X GET "//campaigns" \
  -H "Authorization: Bearer <token>"

Paginated campaign list

{
  "data": [
    {
      "id": 1,
      "brandId": 1,
      "title": "Summer Giveaway 2026",
      "description": "Comment on our post to win!",
      "imageUrl": "string",
      "pointsReward": 100,
      "isActive": true,
      "startsAt": "2019-08-24T14:15:22Z",
      "endsAt": "2019-08-24T14:15:22Z",
      "createdAt": "2019-08-24T14:15:22Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 150
  }
}

Get campaign details

GET
/campaigns/{id}

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger
curl -X GET "//campaigns/{id}" \
  -H "Authorization: Bearer <token>"

Campaign details with challenge info

{
  "data": {
    "id": 1,
    "brandId": 1,
    "title": "Summer Giveaway 2026",
    "description": "Comment on our post to win!",
    "imageUrl": "string",
    "pointsReward": 100,
    "isActive": true,
    "startsAt": "2019-08-24T14:15:22Z",
    "endsAt": "2019-08-24T14:15:22Z",
    "createdAt": "2019-08-24T14:15:22Z",
    "challenge": {
      "id": 1,
      "campaignId": 1,
      "platform": "instagram",
      "contentType": "post",
      "contentId": "ABC123",
      "canonicalUrl": "https://www.instagram.com/p/ABC123/",
      "instructionText": "Leave a comment with #SummerVibes"
    },
    "myAttempt": {
      "id": 0,
      "state": "string",
      "retryCount": 0,
      "createdAt": "2019-08-24T14:15:22Z",
      "updatedAt": "2019-08-24T14:15:22Z"
    }
  }
}

Create campaign with challenge

Creates a campaign and its single challenge in one call. The challenge's platform, content type and content id are parsed from challenge.targetUrl.

pointsReward must be a whole number of 1 or more. It is only spent by engagement verification, but it is required whether or not you use it.

The response's challenge.id is the challengeId every later request takes.

POST
/admin/campaigns

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Request Body

application/jsonRequired
brandIdRequiredinteger
titleRequiredstring
descriptionstring
imageUrlstring
Format: "uri"
pointsRewardRequiredinteger
Minimum: 1
startsAtstring
Format: "date-time"
endsAtstring
Format: "date-time"
challengeRequiredobject
curl -X POST "//admin/campaigns" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "brandId": 1,
    "title": "Summer Challenge 2026",
    "description": "Comment on our Instagram post",
    "imageUrl": "https://example.com/image.jpg",
    "pointsReward": 100,
    "startsAt": "2019-08-24T14:15:22Z",
    "endsAt": "2019-08-24T14:15:22Z",
    "challenge": {
      "targetUrl": "https://www.instagram.com/p/ABC123/",
      "instructionText": "Leave a comment with #SummerVibes",
      "action": "comment"
    }
  }'

Campaign created

{
  "data": {
    "campaign": {
      "id": 1,
      "brandId": 1,
      "title": "Summer Giveaway 2026",
      "description": "Comment on our post to win!",
      "imageUrl": "string",
      "pointsReward": 100,
      "isActive": true,
      "startsAt": "2019-08-24T14:15:22Z",
      "endsAt": "2019-08-24T14:15:22Z",
      "createdAt": "2019-08-24T14:15:22Z"
    },
    "challenge": {
      "id": 1,
      "campaignId": 1,
      "platform": "instagram",
      "contentType": "post",
      "contentId": "ABC123",
      "canonicalUrl": "https://www.instagram.com/p/ABC123/",
      "instructionText": "Leave a comment with #SummerVibes"
    }
  }
}

Get campaign summary stats

Returns attempt counts by state, total verified, rewarded, and points issued.

GET
/admin/campaigns/{id}/summary

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger
curl -X GET "//admin/campaigns/{id}/summary" \
  -H "Authorization: Bearer <token>"

Campaign summary

{
  "data": {
    "campaignId": 1,
    "totalAttempts": 250,
    "byState": {
      "created": 10,
      "verified": 50,
      "rewarded": 180,
      "failed_terminal": 10
    },
    "totalVerified": 230,
    "totalRewarded": 180,
    "totalPointsIssued": 18000
  }
}

Get campaign participant results

GET
/admin/campaigns/{id}/results

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger

Query Parameters

pageinteger
Default: 1
limitinteger
Default: 20
statestring

Filter by attempt state

Value in: "created" | "target_opened" | "awaiting_claim" | "verification_pending" | "verified" | "rewarded" | "failed_retryable" | "failed_terminal"
curl -X GET "//admin/campaigns/{id}/results?state=created" \
  -H "Authorization: Bearer <token>"

Participant results

{
  "data": [
    {}
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 150
  }
}

Batch verify and reward creators

Matches verified creators who have post comments matching their username but no existing attempt. Creates attempts in verified state, enqueues reward jobs, and dispatches creator.verified webhooks (followed by reward.issued once the reward worker runs).

POST
/admin/campaigns/{id}/verify-and-reward

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger
curl -X POST "//admin/campaigns/{id}/verify-and-reward" \
  -H "Authorization: Bearer <token>"

Batch result

{
  "data": {
    "matched": 15,
    "verified": 14,
    "rewarded": 14
  }
}

End campaign

Soft-finish a campaign: sets isActive = false and endsAt to now (or keeps earlier endsAt if already past). Existing attempts and rewards are preserved. Idempotent.

POST
/admin/campaigns/{id}/end

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger
curl -X POST "//admin/campaigns/{id}/end" \
  -H "Authorization: Bearer <token>"

Campaign ended

{
  "data": {
    "id": 1,
    "isActive": false,
    "endsAt": "2019-08-24T14:15:22Z"
  }
}

Delete campaign

Hard-deletes a campaign and its challenge, including stored post comments and metrics. Only permitted when the challenge has zero attempts. If any attempts exist, returns 409 CAMPAIGN_HAS_ACTIVITY — end the campaign instead.

DELETE
/admin/campaigns/{id}

Authorization

AuthorizationRequiredBearer <token>

API token. Send it as Authorization: Bearer <API_TOKEN>.

In: header

Path Parameters

idRequiredinteger
curl -X DELETE "//admin/campaigns/{id}" \
  -H "Authorization: Bearer <token>"

Campaign deleted

{
  "data": {
    "id": 1
  }
}

Last updated on