curl --request POST \
--url https://api.growi.io/api/public/v1/campaign_applications \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"campaign_id": 123,
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"tiktok_handle": "<string>",
"id": 123,
"created_at": "<string>",
"fbp": "<string>",
"fbc": "<string>",
"fbclid": "<string>",
"event_id": "<string>",
"event_name": "<string>",
"event_source_url": "<string>",
"client_ip_address": "<string>",
"client_user_agent": "<string>",
"referrer": "<string>",
"utm_source": "<string>",
"utm_medium": "<string>",
"utm_campaign": "<string>",
"utm_content": "<string>",
"utm_term": "<string>",
"follower_count": 123,
"likes_count": 123,
"video_count": 123,
"tiktok_verified": 123,
"enriched_at": "<string>"
}
'import requests
url = "https://api.growi.io/api/public/v1/campaign_applications"
payload = {
"campaign_id": 123,
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"tiktok_handle": "<string>",
"id": 123,
"created_at": "<string>",
"fbp": "<string>",
"fbc": "<string>",
"fbclid": "<string>",
"event_id": "<string>",
"event_name": "<string>",
"event_source_url": "<string>",
"client_ip_address": "<string>",
"client_user_agent": "<string>",
"referrer": "<string>",
"utm_source": "<string>",
"utm_medium": "<string>",
"utm_campaign": "<string>",
"utm_content": "<string>",
"utm_term": "<string>",
"follower_count": 123,
"likes_count": 123,
"video_count": 123,
"tiktok_verified": 123,
"enriched_at": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
campaign_id: 123,
email: '<string>',
first_name: '<string>',
last_name: '<string>',
tiktok_handle: '<string>',
id: 123,
created_at: '<string>',
fbp: '<string>',
fbc: '<string>',
fbclid: '<string>',
event_id: '<string>',
event_name: '<string>',
event_source_url: '<string>',
client_ip_address: '<string>',
client_user_agent: '<string>',
referrer: '<string>',
utm_source: '<string>',
utm_medium: '<string>',
utm_campaign: '<string>',
utm_content: '<string>',
utm_term: '<string>',
follower_count: 123,
likes_count: 123,
video_count: 123,
tiktok_verified: 123,
enriched_at: '<string>'
})
};
fetch('https://api.growi.io/api/public/v1/campaign_applications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.growi.io/api/public/v1/campaign_applications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'campaign_id' => 123,
'email' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'tiktok_handle' => '<string>',
'id' => 123,
'created_at' => '<string>',
'fbp' => '<string>',
'fbc' => '<string>',
'fbclid' => '<string>',
'event_id' => '<string>',
'event_name' => '<string>',
'event_source_url' => '<string>',
'client_ip_address' => '<string>',
'client_user_agent' => '<string>',
'referrer' => '<string>',
'utm_source' => '<string>',
'utm_medium' => '<string>',
'utm_campaign' => '<string>',
'utm_content' => '<string>',
'utm_term' => '<string>',
'follower_count' => 123,
'likes_count' => 123,
'video_count' => 123,
'tiktok_verified' => 123,
'enriched_at' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.growi.io/api/public/v1/campaign_applications"
payload := strings.NewReader("{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.growi.io/api/public/v1/campaign_applications")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.growi.io/api/public/v1/campaign_applications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {}
}{
"data": {
"invitation_id": 123,
"status": "<string>",
"user_id": 123,
"campaign_id": 123,
"created": true
}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}Create Campaign Application
Submits an applicant from your own signup form directly into a Growi campaign. Creates the creator account if needed and stores marketing attribution (Meta click ids, UTMs, TikTok enrichment) that is echoed back on outbound webhook events. Idempotent: repeat submissions for the same email + campaign return the existing application.
curl --request POST \
--url https://api.growi.io/api/public/v1/campaign_applications \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"campaign_id": 123,
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"tiktok_handle": "<string>",
"id": 123,
"created_at": "<string>",
"fbp": "<string>",
"fbc": "<string>",
"fbclid": "<string>",
"event_id": "<string>",
"event_name": "<string>",
"event_source_url": "<string>",
"client_ip_address": "<string>",
"client_user_agent": "<string>",
"referrer": "<string>",
"utm_source": "<string>",
"utm_medium": "<string>",
"utm_campaign": "<string>",
"utm_content": "<string>",
"utm_term": "<string>",
"follower_count": 123,
"likes_count": 123,
"video_count": 123,
"tiktok_verified": 123,
"enriched_at": "<string>"
}
'import requests
url = "https://api.growi.io/api/public/v1/campaign_applications"
payload = {
"campaign_id": 123,
"email": "<string>",
"first_name": "<string>",
"last_name": "<string>",
"tiktok_handle": "<string>",
"id": 123,
"created_at": "<string>",
"fbp": "<string>",
"fbc": "<string>",
"fbclid": "<string>",
"event_id": "<string>",
"event_name": "<string>",
"event_source_url": "<string>",
"client_ip_address": "<string>",
"client_user_agent": "<string>",
"referrer": "<string>",
"utm_source": "<string>",
"utm_medium": "<string>",
"utm_campaign": "<string>",
"utm_content": "<string>",
"utm_term": "<string>",
"follower_count": 123,
"likes_count": 123,
"video_count": 123,
"tiktok_verified": 123,
"enriched_at": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
campaign_id: 123,
email: '<string>',
first_name: '<string>',
last_name: '<string>',
tiktok_handle: '<string>',
id: 123,
created_at: '<string>',
fbp: '<string>',
fbc: '<string>',
fbclid: '<string>',
event_id: '<string>',
event_name: '<string>',
event_source_url: '<string>',
client_ip_address: '<string>',
client_user_agent: '<string>',
referrer: '<string>',
utm_source: '<string>',
utm_medium: '<string>',
utm_campaign: '<string>',
utm_content: '<string>',
utm_term: '<string>',
follower_count: 123,
likes_count: 123,
video_count: 123,
tiktok_verified: 123,
enriched_at: '<string>'
})
};
fetch('https://api.growi.io/api/public/v1/campaign_applications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.growi.io/api/public/v1/campaign_applications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'campaign_id' => 123,
'email' => '<string>',
'first_name' => '<string>',
'last_name' => '<string>',
'tiktok_handle' => '<string>',
'id' => 123,
'created_at' => '<string>',
'fbp' => '<string>',
'fbc' => '<string>',
'fbclid' => '<string>',
'event_id' => '<string>',
'event_name' => '<string>',
'event_source_url' => '<string>',
'client_ip_address' => '<string>',
'client_user_agent' => '<string>',
'referrer' => '<string>',
'utm_source' => '<string>',
'utm_medium' => '<string>',
'utm_campaign' => '<string>',
'utm_content' => '<string>',
'utm_term' => '<string>',
'follower_count' => 123,
'likes_count' => 123,
'video_count' => 123,
'tiktok_verified' => 123,
'enriched_at' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.growi.io/api/public/v1/campaign_applications"
payload := strings.NewReader("{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.growi.io/api/public/v1/campaign_applications")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.growi.io/api/public/v1/campaign_applications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"campaign_id\": 123,\n \"email\": \"<string>\",\n \"first_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"tiktok_handle\": \"<string>\",\n \"id\": 123,\n \"created_at\": \"<string>\",\n \"fbp\": \"<string>\",\n \"fbc\": \"<string>\",\n \"fbclid\": \"<string>\",\n \"event_id\": \"<string>\",\n \"event_name\": \"<string>\",\n \"event_source_url\": \"<string>\",\n \"client_ip_address\": \"<string>\",\n \"client_user_agent\": \"<string>\",\n \"referrer\": \"<string>\",\n \"utm_source\": \"<string>\",\n \"utm_medium\": \"<string>\",\n \"utm_campaign\": \"<string>\",\n \"utm_content\": \"<string>\",\n \"utm_term\": \"<string>\",\n \"follower_count\": 123,\n \"likes_count\": 123,\n \"video_count\": 123,\n \"tiktok_verified\": 123,\n \"enriched_at\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {}
}{
"data": {
"invitation_id": 123,
"status": "<string>",
"user_id": 123,
"campaign_id": 123,
"created": true
}
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}{
"error": "<string>",
"message": "<string>"
}email + campaign_id return the existing application with created: false instead of creating a duplicate. Attribution keys not seen before are merged in; existing values are never overwritten. This endpoint is also exempt from the 2-second request-interval limit, so bursts of near-simultaneous form submissions are safe.
Request Body
| Field | Type | Description | Required |
|---|---|---|---|
campaign_id | Integer | Growi campaign the applicant is applying to | Yes |
email | String | Applicant’s email address | Yes |
first_name | String | Applicant’s first name | No |
last_name | String | Applicant’s last name | No |
tiktok_handle | String | TikTok handle or profile URL; attached to the creator’s profile | No |
id | Integer | Your internal applicant id, stored as attribution external_id | No |
created_at | String | When the applicant submitted your form, stored as attribution submitted_at | No |
Attribution fields (all optional)
Everything below is stored verbatim and echoed back inside theattribution object on webhook events.
| Field | Type | Description |
|---|---|---|
fbp | String | Meta browser id cookie (_fbp) |
fbc | String | Meta click id cookie (_fbc) |
fbclid | String | Meta click id from the landing page URL |
event_id | String | Your event id — use it to deduplicate against Meta Conversions API |
event_name | String | Your event name (e.g. AffiliateLead) |
event_source_url | String | URL the applicant submitted the form from |
client_ip_address | String | Applicant’s IP address |
client_user_agent | String | Applicant’s browser user agent |
referrer | String | HTTP referrer of the signup page |
utm_source / utm_medium / utm_campaign / utm_content / utm_term | String | UTM parameters from the landing URL |
follower_count | Integer | Applicant’s TikTok follower count |
likes_count | Integer | Applicant’s TikTok likes count |
video_count | Integer | Applicant’s TikTok video count |
tiktok_verified | Integer | 1 when the TikTok account is verified |
enriched_at | String | When you enriched the TikTok profile data |
Request Example
curl -X POST "https://api.growi.io/api/public/v1/campaign_applications" \
-H "Authorization: Bearer YOUR_PUBLIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": 51812,
"email": "maria.92.ambriz@gmail.com",
"first_name": "Maria",
"last_name": "Ambriz",
"tiktok_handle": "maria.ambriz66",
"id": 11177,
"created_at": "2026-07-31 13:13:16",
"fbp": "fb.1.1785503550741.5188770206",
"fbc": "fb.1.1785503550741.PAcGRvZgJmZGlk",
"fbclid": "PAcGRvZgJmZGlk",
"event_id": "012e8a42-6b26-43cf-9a66-0242c6bc0fd1",
"event_name": "AffiliateLead",
"event_source_url": "https://shop.example.com/tiktok-partner?utm_source=facebook",
"client_ip_address": "203.0.113.7",
"client_user_agent": "Mozilla/5.0 (iPhone)",
"referrer": "https://instagram.com/",
"utm_source": "facebook",
"utm_medium": "paid",
"utm_campaign": "COFFEE | LEAD | BOF",
"follower_count": 2992,
"likes_count": 16000,
"video_count": 139,
"tiktok_verified": 1
}'
Response Example
{
"data": {
"invitation_id": 98123,
"status": "pending",
"user_id": 45678,
"campaign_id": 51812,
"created": true
}
}
200 with the same shape and "created": false.
Response Fields
| Field | Type | Description |
|---|---|---|
data.invitation_id | Integer | The application’s id |
data.status | String | pending, or accepted when the campaign auto-accepts applicants |
data.user_id | Integer | The creator’s Growi user id |
data.campaign_id | Integer | The campaign applied to |
data.created | Boolean | true for a new application, false for an idempotent repeat |
Error Responses
403 — plan or key{ "error": "The applications API is not enabled for your plan." }
{ "error": "Campaign not found." }
{ "error": "email is required" }
Use Cases
- Host your own signup form: keep the application experience on your domain (with your pixels and analytics firing natively) while applicants flow straight into Growi for review.
- Meta ads attribution: send
fbp/fbc/event_idwith each applicant, then forward thecampaign_affiliate.activatedandaffiliate_sale.createdwebhook events — which echo the same identifiers — to the Meta Conversions API so your media team can optimize on approvals and revenue. - CRM sync: pass your internal applicant
id; it comes back asattribution.external_idon webhook events for painless matching.
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Growi campaign the applicant is applying to
Applicant's email address
Applicant's first name
Applicant's last name
TikTok handle or profile URL — the account is attached to the creator's profile
Your internal applicant id, stored as attribution external_id
When the applicant submitted your form, stored as attribution submitted_at
Meta browser id cookie (_fbp)
Meta click id cookie (_fbc)
Meta click id from the landing page URL
Your event id — echoed back on webhook events so you can deduplicate against Meta Conversions API
Your event name (e.g. AffiliateLead)
URL the applicant submitted the form from
Applicant's IP address
Applicant's browser user agent
HTTP referrer of the signup page
Applicant's TikTok follower count
Applicant's TikTok likes count
Applicant's TikTok video count
1 when the TikTok account is verified
When you enriched the TikTok profile data
Response
Repeat submission — the existing application is returned and new attribution keys are merged