> For the complete documentation index, see [llms.txt](https://docs.uppercut.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uppercut.co/integration/track-sales-api.md).

# Track Sales (API)

{% hint style="info" %}
The API-based tracking might require a developer on your team. If you do not have any development experience or are using pre-built themes, consider using a pre-built integration like [Track Sales (Stripe)](/integration/track-sales-stripe.md)
{% endhint %}

The API is an easy lightweight way of tracking new sales and attributing commissions to your affiliates. The integration only takes two steps.

### Grab your API key

API keys can be generated through your dashboard. The key will only be shown to you once, so make sure you copy and save it somewhere save.

You'll use the API key to make authenticated calls to our API, sending it in the request header.

```
Authorization: Api-Key <API_KEY>
```

### Track sales

When a new sale is made, send the purchase information to our API to convert it into a commission.

Note – send all new sales to this endpoint. We'll do our job in making sure only referred sales are being collected in the program.

#### Parameters

* **event\_id**: A unique identifier for this sale, can for example be the payment ID from your external billing system or an automatically generated identifier you're keeping track of.
* **amount**: USD amount of the *sale*. We'll use this value to calculate the commission according to your campaign settings.
* **email:** Email of the user. Should correspond to the email tracked when [Tracking Script](/integration/tracking-script.md#track-signups)
* **userId*****:*** User ID as it was set during [Tracking Script](/integration/tracking-script.md#track-signups), can be alphanumerical and include special characters.

Only one of "email" and "userId" is required. However, it is recommended you add both.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" lineNumbers="true" %}

```javascript
fetch('https://app.uppercut.co/api/track-sale', {
  method: 'POST',
  headers: {
    'Authorization': 'Api-Key <API_KEY>',
    'Content-type': 'application/json'
  },
  body: JSON.stringify({
    'event_id': '<payment_id>',
    'amount': 130,
    'email': 'customer@example.com',
    'userId': '1234'
  })
});
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}

<pre class="language-python" data-overflow="wrap" data-line-numbers><code class="lang-python">import requests

headers = {
    'Authorization': 'Api-Key &#x3C;API_KEY>'
}

json_data = {
    'event_id': '&#x3C;payment_id>',
    'amount': 130.0,
    'email': 'customer@example.com',
    'userId': '1234'
}

<strong>requests.post('https://app.uppercut.co/api/track-sale', headers=headers, json=json_data)
</strong></code></pre>

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'net/http'
require 'json'

uri = URI('https://app.uppercut.co/api/track-sale')
req = Net::HTTP::Post.new(uri)
req.content_type = 'application/json'
req['Authorization'] = 'Api-Key <API_KEY>'

req.body = {
  'event_id' => '<payment_id>',
  'amount' => 130,
  'email' => 'customer@example.com',
  'userId' => '1234'
}.to_json

req_options = {
  use_ssl: uri.scheme == 'https'
}
res = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(req)
end
```

{% endtab %}

{% tab title="curl" %}
{% code overflow="wrap" lineNumbers="true" %}

```sh
curl -XPOST -H 'Authorization: Api-Key <API_KEY>' -H "Content-type: application/json" -d '{"event_id": "<payment_id>", "amount": 130.0, "email": "customer@example.com" "userId": "1234"}' 'https://app.uppercut.co/api/track-sale'
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Track refunds (optional)

When a refund happens, you can decide to take back the commission as well. This is recommended when your product receives many refund requests.

#### Parameters

* **event\_id**: The event ID you originally used to track the sale.

{% tabs %}
{% tab title="JavaScript" %}
{% code overflow="wrap" lineNumbers="true" %}

```javascript
fetch('https://app.uppercut.co/api/track-refund', {
  method: 'POST',
  headers: {
    'Authorization': 'Api-Key <API_KEY>',
    'Content-type': 'application/json'
  },
  body: JSON.stringify({
    'event_id': '<payment_id>'
  })
});

```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code overflow="wrap" lineNumbers="true" %}

```python
import requests

headers = {
    'Authorization': 'Api-Key <API_KEY>'
}

json_data = {
    'event_id': '<payment_id>',
}

response = requests.post('https://app.uppercut.co/api/track-refund', headers=headers, json=json_data)

```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code overflow="wrap" lineNumbers="true" %}

```ruby
require 'net/http'
require 'json'

uri = URI('https://app.uppercut.co/api/track-refund')
req = Net::HTTP::Post.new(uri)
req.content_type = 'application/json'
req['Authorization'] = 'Api-Key <API_KEY>'

# The object won't be serialized exactly like this
# req.body = '{"event_id": "<payment_id>"}'
req.body = {
  'event_id' => '<payment_id>'
}.to_json

req_options = {
  use_ssl: uri.scheme == 'https'
}
res = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
  http.request(req)
end
```

{% endcode %}
{% endtab %}

{% tab title="curl" %}
{% code overflow="wrap" lineNumbers="true" %}

```sh
curl -XPOST -H 'Authorization: Api-Key <API_KEY>' -H  -H "Content-type: application/json" -d '{"event_id": "<payment_id>"}' 'https://app.uppercut.co/api/track-refund'
```

{% endcode %}
{% endtab %}
{% endtabs %}
