openapi: 3.2.0 info: title: FirstPromoter Tracking API V2 Sale API description: Our tracking API allows companies to track any type of signups, sales, cancellations and refunds for any billing provider, you are not limited to our built-in integrations with Stripe, Chargebee, Recurly and Braintree. license: name: MIT version: 1.0.0 servers: - url: https://api.firstpromoter.com/api/v2/track security: - BearerAuth: [] tags: - name: Sale paths: /sale: post: description: Assign sales and commissions to your promoters. To track sales and generate commissions correctly, you need to use this API call each time a non-zero amount sale is processed in your system, even if it comes from a recurring charge or one-time charge. To avoid fraudulent sales, we don't use JS conversion pixels to track sales, which are very unreliable and can be easily faked. Instead, we use server-side tracking for all sales to ensure that a sale is tracked only when you actually receive money in your billing account.

To maintain the same standards with the API, we recommend making the sale API call (this call) only when you receive confirmation of the sale from your billing provider, such as from a webhook, an IPN, or a success response from an API charge call.

You just need to pass the sale amount (before taxes) and we'll take care of the rest. The commissions/rewards will be calculated based on that amount and the plan ID, in case you use the plan-level rewards feature.
Using email or UID parameters, we identify the lead/customer who generated the sale, which also helps us determine the promoter who owns the reward/commission.

The lead is added to our system either by the client signup tracking script when the user signs up or by calling the signup API endpoint. There is also the option to bypass the signup tracking by using TID or ref_id parameters, which will create the lead and assign the sale in one go.

**If we don't find the lead in our system, then it means that the sale is not a referral sale, you'll get a 404 response. Also, if the promoter is banned, you'll get a 404 response. You don't have to identify which sale is from referrals and which is not; we'll take care of that.** **For zero-decimal** currencies like `JPY`, `amount` and `mrr` parameters should be sent as **whole values**.

**For other currencies**, `amount` and `mrr` parameter values should be in cents, i.e., you will need to **multiply the value by 100** before sending the request.
**HTTP Request**
`POST https://api.firstpromoter.com/api/v2/track/sale`
parameters: - $ref: '#/components/parameters/AccountId' requestBody: required: true content: application/json: schema: type: object required: - event_id - amount properties: email: type: string description: Email of the lead/sign-up. Required if uid is not provided. uid: type: string description: uid of the lead added on signup tracking. Required if email is not provided. event_id: type: string description: Transaction or sale event ID. Required to avoid duplicate sales. amount: type: integer description: The sale amount in cents. For zero-decimal currencies like JPY, amount should be whole values. quantity: type: integer description: Number of subscriptions/items. Optional if quantity is 1. plan: type: string description: Customer plan ID from billing provider. Used for plan-level rewards. currency: type: string description: Required only if different from FirstPromoter settings default currency. mrr: type: string description: Monthly Recurring Revenue generated by the customer. promo_code: type: string description: For promo code tracking. tid: type: string description: Visitor tracking ID from _fprom_tid cookie. ref_id: type: string description: Referral ID of the promoter. skip_email_notification: type: boolean description: Set true to skip email notifications. Default is false. oneOf: - required: - email - required: - uid responses: '200': description: Sale tracked successfully content: application/json: schema: type: object properties: id: type: integer example: 45831949 etype: type: string example: sale sale_amount: type: integer example: 2000 original_sale_amount: type: integer example: 2000 original_sale_currency: type: - string - 'null' example: null event_id: type: - string - 'null' example: null plan_id: type: - string - 'null' example: null billing_period: type: - string - 'null' example: null created_at: type: string format: date-time example: '2025-04-25T09:39:42.289Z' referral: type: object properties: id: type: integer example: 29203686 email: type: string example: testme@test1.com uid: type: - string - 'null' example: null commissions: type: array items: type: object properties: id: type: integer example: 13533003 status: type: string example: approved metadata: type: object example: {} is_self_referral: type: boolean example: false commission_type: type: string example: sale created_by_user_email: type: - string - 'null' example: null created_by_user_at: type: - string - 'null' example: null sale_amount: type: integer example: 2000 original_sale_amount: type: integer example: 2000 original_sale_currency: type: - string - 'null' example: null event_id: type: - string - 'null' example: null plan_id: type: - string - 'null' example: null tier: type: integer example: 1 internal_note: type: - string - 'null' example: null external_note: type: - string - 'null' example: null unit: type: string example: cash fraud_check: type: string example: no_suspicion amount: type: integer example: 400 is_paid: type: boolean example: false is_split: type: boolean example: false created_at: type: string format: date-time example: '2025-04-25T09:39:42Z' status_updated_at: type: - string - 'null' example: null promoter_campaign: type: object properties: id: type: integer example: 14850130 campaign_id: type: integer example: 28004 promoter_id: type: integer example: 8262622 created_at: type: string format: date-time example: '2025-01-16T18:16:41Z' promoter: type: object properties: id: type: integer example: 8262622 email: type: string example: test@promoter.com name: type: string example: Test Promoter campaign: type: object properties: id: type: integer example: 28004 name: type: string example: Quinn Ramirez color: type: string example: '#EC4899' referral: type: object properties: id: type: integer example: 29203686 email: type: string example: testme@test1.com uid: type: - string - 'null' example: null reward: type: object properties: id: type: integer example: 157427 name: type: string example: 20% recurring commission '404': description: Not Found content: application/json: schema: type: object properties: message: type: string example: Referral corresponding to email or uid parameter not found or promoter is banned. code: type: string example: not_found '400': description: Bad Request content: application/json: schema: type: object properties: message: type: string example: Error. Amount blank or invalid. '409': description: Conflict content: application/json: schema: type: object properties: message: type: string example: The 'sale' event with the id 'test_sale_12340987' already exists. tags: - Sale components: parameters: AccountId: name: Account-ID in: header required: true description: Account id. You can find your Account ID on Your FirstPromoter Dashboard. Navigate to Settings → Integrations schema: type: string securitySchemes: BearerAuth: type: http scheme: bearer description: API key passed as a Bearer token in the Authorization header. You can find your API Key on Your FirstPromoter Dashboard. Navigate to Settings → Integrations section → Manage API Keys accountId: type: apiKey in: header name: ACCOUNT-ID description: Your FirstPromoter Account ID. You can find this in the Settings → Integrations section of your dashboard.