Skip to main content
POST
/
affiliate_sales
cURL
curl --request POST \
  --url https://api.growi.io/api/public/v1/affiliate_sales \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "order_id": "<string>",
  "currency": "usd",
  "total": 123,
  "subtotal": 123,
  "campaign_affiliate_id": "<string>",
  "growi_user_id": 123,
  "growi_campaign_id": 123,
  "occurred_at": "2023-11-07T05:31:56Z",
  "due_at": "2023-11-07T05:31:56Z",
  "customer_email": "jsmith@example.com",
  "customer_name": "<string>",
  "visitor_uid": "<string>",
  "sale_type": "one_time",
  "commission": 123
}
'
{
  "data": {
    "id": 1947457,
    "external_id": "ORD-12345",
    "platform": "website",
    "status": "unpaid",
    "occurred_at": "2025-09-30T23:55:29.000Z",
    "total": 9999,
    "commission": 500,
    "currency": "usd"
  }
}
Creates a website conversion and attributes it to a campaign affiliate. Use this endpoint to report conversions from your website, custom checkout flows, or server-side integrations. This endpoint is idempotent: sending the same order_id again returns the existing sale with a 201 status code, making it safe for webhook handlers and retry logic.

Attribution Methods

You can attribute the sale using one of two methods:
  1. Affiliate Tag (campaign_affiliate_id): Use the creator’s unique affiliate tag/code
  2. Growi IDs (growi_user_id + growi_campaign_id): Use the Growi user ID and campaign ID directly

Request Body

FieldTypeDescriptionRequired
order_idStringYour unique order/transaction identifierYes
totalIntegerTotal order amount in cents (e.g., 9999 = $99.99). At least one of total or subtotal is required.Conditional
subtotalIntegerOrder subtotal in cents (before shipping/tax). At least one of total or subtotal is required.Conditional
currencyStringCurrency code: usd, eur, gbp, etc.Yes
campaign_affiliate_idStringAffiliate tag for attribution (required if not using growi_user_id + growi_campaign_id)Conditional
growi_user_idIntegerGrowi user ID (required with growi_campaign_id if not using campaign_affiliate_id)Conditional
growi_campaign_idIntegerGrowi campaign ID (required with growi_user_id if not using campaign_affiliate_id)Conditional
occurred_atStringISO 8601 timestamp when the sale occurred. Defaults to current time.No
due_atStringISO 8601 timestamp when commission becomes dueNo
customer_emailStringCustomer’s email addressNo
customer_nameStringCustomer’s nameNo
visitor_uidStringVisitor unique identifier (for tracking purposes)No
sale_typeStringType of sale: one_time or subscription. Default is one_time.No
commissionIntegerOverride commission amount in cents. If omitted, calculated from campaign rules.No

Request Example

Using affiliate tag:
curl -X POST "https://api.growi.io/api/public/v1/affiliate_sales" \
     -H "Authorization: Bearer YOUR_PUBLIC_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "order_id": "ORD-12345",
       "total": 9999,
       "currency": "usd",
       "campaign_affiliate_id": "SUMMER2025",
       "occurred_at": "2025-09-30T12:00:00Z"
     }'
Using Growi IDs:
curl -X POST "https://api.growi.io/api/public/v1/affiliate_sales" \
     -H "Authorization: Bearer YOUR_PUBLIC_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
       "order_id": "ORD-67890",
       "total": 4999,
       "currency": "usd",
       "growi_user_id": 12345,
       "growi_campaign_id": 16200,
       "occurred_at": "2025-09-30T14:30:00Z"
     }'

Response Example

201 Created - Sale created successfully (or already exists with same order_id):
{
  "data": {
    "id": 1947458,
    "external_id": "ORD-12345",
    "platform": "website",
    "status": "unpaid",
    "occurred_at": "2025-09-30T12:00:00.000Z",
    "total": 9999,
    "commission": 500,
    "currency": "usd"
  }
}

Response Fields

FieldTypeDescription
dataObjectThe created affiliate sale object
data.idIntegerUnique Growi identifier for the sale
data.external_idStringYour order ID (same as the order_id you provided)
data.platformStringAlways website for sales created via this endpoint
data.statusStringInitial status: unpaid
data.occurred_atStringISO 8601 timestamp when the sale occurred
data.totalIntegerTotal order amount in cents
data.commissionIntegerCommission amount in cents (calculated or overridden)
data.currencyStringCurrency code

Error Responses

422 Unprocessable Entity - Missing required fields or invalid attribution:
{
  "error": "Order ID is required."
}
{
  "error": "Currency is required."
}
{
  "error": "Total or subtotal is required."
}
{
  "error": "Attribution required: provide campaign_affiliate_id OR both growi_user_id and growi_campaign_id."
}
{
  "error": "Campaign affiliate not found."
}

Use Cases

This endpoint is useful for:
  • Server-Side Conversion Tracking: Report conversions from your backend after a successful checkout
  • Custom Checkout Flows: Integrate with headless commerce or custom payment systems
  • Webhook Handlers: Process payment webhooks (idempotent design ensures safe retries)
  • CRM Integration: Create conversions when deals close in your CRM
  • Manual Attribution: Attribute offline or phone sales to specific creators
  • Commission Override: Specify custom commission amounts for special promotions

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
order_id
string
required

Your unique order/transaction identifier

currency
enum<string>
required

Currency code

Available options:
usd,
eur,
gbp
total
integer

Total order amount in cents. At least one of total or subtotal is required.

subtotal
integer

Order subtotal in cents. At least one of total or subtotal is required.

campaign_affiliate_id
string

Affiliate tag for attribution (required if not using growi_user_id + growi_campaign_id)

growi_user_id
integer

Growi user ID (required with growi_campaign_id if not using campaign_affiliate_id)

growi_campaign_id
integer

Growi campaign ID (required with growi_user_id if not using campaign_affiliate_id)

occurred_at
string<date-time>

When the sale occurred (ISO 8601)

due_at
string<date-time>

When commission becomes due

customer_email
string<email>

Customer email address

customer_name
string

Customer name

visitor_uid
string

Visitor unique identifier

sale_type
enum<string>
default:one_time

Type of sale

Available options:
one_time,
subscription
commission
integer

Override commission amount in cents

Response

Affiliate sale created successfully

data
object