> ## Documentation Index
> Fetch the complete documentation index at: https://growi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Affiliate Sale

> Creates a website conversion and attributes it to a campaign affiliate. Idempotent: sending the same order_id returns the existing sale.

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

| Field                   | Type    | Description                                                                                                | Required    |
| ----------------------- | ------- | ---------------------------------------------------------------------------------------------------------- | ----------- |
| `order_id`              | String  | Your unique order/transaction identifier                                                                   | Yes         |
| `total`                 | Integer | Total order amount in **cents** (e.g., 9999 = \$99.99). At least one of `total` or `subtotal` is required. | Conditional |
| `subtotal`              | Integer | Order subtotal in **cents** (before shipping/tax). At least one of `total` or `subtotal` is required.      | Conditional |
| `currency`              | String  | Currency code: `usd`, `eur`, `gbp`, etc.                                                                   | Yes         |
| `campaign_affiliate_id` | String  | Affiliate tag for attribution (required if not using growi\_user\_id + growi\_campaign\_id)                | Conditional |
| `growi_user_id`         | Integer | Growi user ID (required with growi\_campaign\_id if not using campaign\_affiliate\_id)                     | Conditional |
| `growi_campaign_id`     | Integer | Growi campaign ID (required with growi\_user\_id if not using campaign\_affiliate\_id)                     | Conditional |
| `occurred_at`           | String  | ISO 8601 timestamp when the sale occurred. Defaults to current time.                                       | No          |
| `due_at`                | String  | ISO 8601 timestamp when commission becomes due                                                             | No          |
| `customer_email`        | String  | Customer's email address                                                                                   | No          |
| `customer_name`         | String  | Customer's name                                                                                            | No          |
| `visitor_uid`           | String  | Visitor unique identifier (for tracking purposes)                                                          | No          |
| `sale_type`             | String  | Type of sale: `one_time` or `subscription`. Default is `one_time`.                                         | No          |
| `commission`            | Integer | Override commission amount in **cents**. If omitted, calculated from campaign rules.                       | No          |

## Request Example

Using affiliate tag:

```bash theme={null}
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:

```bash theme={null}
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):

```json theme={null}
{
  "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

| Field              | Type    | Description                                           |
| ------------------ | ------- | ----------------------------------------------------- |
| `data`             | Object  | The created affiliate sale object                     |
| `data.id`          | Integer | Unique Growi identifier for the sale                  |
| `data.external_id` | String  | Your order ID (same as the `order_id` you provided)   |
| `data.platform`    | String  | Always `website` for sales created via this endpoint  |
| `data.status`      | String  | Initial status: `unpaid`                              |
| `data.occurred_at` | String  | ISO 8601 timestamp when the sale occurred             |
| `data.total`       | Integer | Total order amount in cents                           |
| `data.commission`  | Integer | Commission amount in cents (calculated or overridden) |
| `data.currency`    | String  | Currency code                                         |

## Error Responses

**422 Unprocessable Entity** - Missing required fields or invalid attribution:

```json theme={null}
{
  "error": "Order ID is required."
}
```

```json theme={null}
{
  "error": "Currency is required."
}
```

```json theme={null}
{
  "error": "Total or subtotal is required."
}
```

```json theme={null}
{
  "error": "Attribution required: provide campaign_affiliate_id OR both growi_user_id and growi_campaign_id."
}
```

```json theme={null}
{
  "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


## OpenAPI

````yaml POST /affiliate_sales
openapi: 3.0.1
info:
  title: Growi API
  description: >-
    API documentation for Growi platform, showcasing the public tracking event
    endpoint
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.growi.io/api/public/v1
security:
  - bearerAuth: []
paths:
  /affiliate_sales:
    post:
      description: >-
        Creates a website conversion and attributes it to a campaign affiliate.
        Idempotent: sending the same order_id returns the existing sale.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewAffiliateSale'
      responses:
        '201':
          description: Affiliate sale created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/AffiliateSale'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Validation error or campaign affiliate not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Order ID is required.
                    description: Error message
components:
  schemas:
    NewAffiliateSale:
      type: object
      required:
        - order_id
        - currency
      properties:
        order_id:
          type: string
          description: Your unique order/transaction identifier
        total:
          type: integer
          description: >-
            Total order amount in cents. At least one of total or subtotal is
            required.
        subtotal:
          type: integer
          description: >-
            Order subtotal in cents. At least one of total or subtotal is
            required.
        currency:
          type: string
          enum:
            - usd
            - eur
            - gbp
          description: Currency code
        campaign_affiliate_id:
          type: string
          description: >-
            Affiliate tag for attribution (required if not using growi_user_id +
            growi_campaign_id)
        growi_user_id:
          type: integer
          description: >-
            Growi user ID (required with growi_campaign_id if not using
            campaign_affiliate_id)
        growi_campaign_id:
          type: integer
          description: >-
            Growi campaign ID (required with growi_user_id if not using
            campaign_affiliate_id)
        occurred_at:
          type: string
          format: date-time
          description: When the sale occurred (ISO 8601)
        due_at:
          type: string
          format: date-time
          description: When commission becomes due
        customer_email:
          type: string
          format: email
          description: Customer email address
        customer_name:
          type: string
          description: Customer name
        visitor_uid:
          type: string
          description: Visitor unique identifier
        sale_type:
          type: string
          enum:
            - one_time
            - subscription
          default: one_time
          description: Type of sale
        commission:
          type: integer
          description: Override commission amount in cents
    AffiliateSale:
      type: object
      properties:
        id:
          type: integer
          example: 1947457
          description: Unique Growi identifier for the sale
        external_id:
          type: string
          example: ORD-12345
          description: External order ID
        platform:
          type: string
          example: website
          description: Source platform
        status:
          type: string
          example: unpaid
          enum:
            - paid
            - due
            - unpaid
            - canceled
            - refunded
          description: Sale status
        occurred_at:
          type: string
          format: date-time
          example: '2025-09-30T23:55:29.000Z'
          description: When the sale occurred
        total:
          type: integer
          example: 9999
          description: Total amount in cents
        commission:
          type: integer
          example: 500
          description: Commission amount in cents
        currency:
          type: string
          example: usd
          description: Currency code
    Error:
      required:
        - error
        - message
      type: object
      properties:
        error:
          type: string
        message:
          type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````