> For the complete documentation index, see [llms.txt](https://woowup-docs.gitbook.io/woowup-developer-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://woowup-docs.gitbook.io/woowup-developer-docs/master.md).

# Getting Started (EN)

## Getting started

This is a REST-style API that uses JSON for serialization. To start using the API you will need:

  1.Log into WoowUp and get your Api Key from the Configuration/MyAccount section. \
  2.Read the API docs to understand what you can do.

Basics

* All request receive and return data in JSON format.
* Remember to include in the header Basic Authentication when calling any endpoint. [Here](/woowup-developer-docs/master.md#authentication) you’ll find how to do it.
* To identify a customer use the field “service\_uid”. Normally you will use the email or the ID (DNI, CPF, RUT, Passport) to identify the customer.
* Every time you are going to use service\_uid as part of the URL, first you’ll need to encode it with base64 and then with url encode. You can read here a detailed explanation [here](/woowup-developer-docs/master.md#how-to-encode-service_uid).
* Valid date formats are: YYYY-mm-dd HH:mm:ss (default in UTC) or ISO8601 format including the timezone Ex: 2004-02-12T15:19:21+03:00
* Normally you’ll include al the Product Information (sku, title, category, stock, etc) within the Create purchase order endpoint. But if you prefer, there is a specific endpoint to synchronize [products](/woowup-developer-docs/api/products.md#products).
* Before send a purchase order, you need to create the customer if it doesn't exist. In the example you can see how this process works in the "import\_from\_csv.php" file.
* Please, pay attention to the messages of the responses of our API because we will tell you if something is wrong with your requests or the information you send.

### Rate Limiting

The API limits the number of requests per account to ensure service stability. **The default limit is 140 requests per minute.**

The system divides time into 30-second segments and always evaluates two segments: the current one and the previous one. Requests from the current segment count at 100%, while requests from the previous segment are weighted based on elapsed time — the more time has passed, the less they count.

This creates a smooth transition between windows, avoiding the classic fixed-counter problem where a client can double the limit at the reset boundary.

{% code lineNumbers="true" %}

```java
weight     = 1 - (elapsed_seconds / segment_duration)                                                                                                                 
estimated  = (previous_requests × weight) + current_requests                                                                                                          
                                                                                                                                                                        
if estimated ≥ limit → HTTP 429 
```

{% endcode %}

**Example:** The previous segment ended with 60 requests and the current one has 25, at 15 seconds into the segment:

{% code lineNumbers="true" %}

```java
weight    = 1 - (15 / 30) = 0.5                                                                                                                                       
estimated = (60 × 0.5) + 25 = 55 → Allowed (< 70)
```

{% endcode %}

#### Response Headers

Every API response includes rate limiting headers so you can monitor your usage:

<table><thead><tr><th>Header</th><th width="373.6328125">Description</th><th width="145.015625">Example</th></tr></thead><tbody><tr><td><code>x-rate-limit-limit</code></td><td><code>Maximum requests per window</code></td><td><code>70</code></td></tr><tr><td><code>x-rate-limit-remaining</code></td><td><code>Remaining requests in current window</code> </td><td><code>45</code></td></tr><tr><td><code>x-rate-limit-reset</code></td><td><code>Unix timestamp when the window resets</code></td><td><code>1742121660</code></td></tr></tbody></table>

When the limit is exceeded, the API responds with HTTP 429 Too Many Requests and includes:

<table><thead><tr><th>Header</th><th width="373.6328125">Description</th><th width="145.015625">Example</th></tr></thead><tbody><tr><td><code>Retry-After</code> </td><td><code>Seconds to wait before retrying</code></td><td><code>18</code></td></tr></tbody></table>

**Example Responses:**

{% tabs %}
{% tab title="Normal Response" %}
`HTTP/1.1 200 OK x-rate-limit-limit: 70 x-rate-limit-remaining: 45 x-rate-limit-reset: 1742121660`
{% endtab %}

{% tab title="Rate Limited Response" %} <sup>`HTTP/1.1 429 Too Many Requests x-rate-limit-limit: 70 x-rate-limit-remaining: 0 x-rate-limit-reset: 1742121660 Retry-After: 18`</sup>

<sup>`{"payload": [], "message": "too many request", "code": "too_many_request"}`</sup>
{% endtab %}
{% endtabs %}

#### Best Practices

* Monitor headers: Check x-rate-limit-remaining on each response to track your usage before hitting the limit.
* Retry with backoff: When you receive a 429, wait the number of seconds indicated in the Retry-After header before retrying.
* Distribute requests: Spread your calls evenly over time instead of sending bursts.
* Use pagination efficiently: Use higher limit values (e.g., ?limit=100) to reduce the number of requests needed.

If you need a higher rate limit, please contact your account manager or our support team.

#### Examples

{% tabs %}
{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
import requests
import time                                                                                                                                                          

BASE_URL = "https://api.woowup.com/apiv3"                                                                                                                            
API_TOKEN = "your_api_token"                                       
                                          
headers = {                                                                                                                                                          
  "Authorization": f"Bearer {API_TOKEN}",
  "Accept": "application/json"                                                                                                                                     
}                                                                  
                                                                                                                                                                   
def make_request(endpoint):                                        
  response = requests.get(f"{BASE_URL}/{endpoint}", headers=headers)

  # Read rate limit headers                                                                                                                                        
  limit = response.headers.get("x-rate-limit-limit")
  remaining = response.headers.get("x-rate-limit-remaining")                                                                                                       
  reset = response.headers.get("x-rate-limit-reset")                                                                                                               
                                          
  print(f"Limit: {limit}, Remaining: {remaining}, Reset: {reset}")                                                                                                 
                                                                 
  if response.status_code == 429:                                                                                                                                  
      retry_after = int(response.headers.get("Retry-After", 30))
      print(f"Rate limited. Retrying in {retry_after}s...")                                                                                                        
      time.sleep(retry_after)                                    
      return make_request(endpoint)
                                                                                                                                                                   
  return response.json()              
                                                                                                                                                                   
result = make_request("/users") 
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Node.js)" %}
{% code lineNumbers="true" %}

```typescript
const BASE_URL = "https://api.woowup.com/apiv3";
const API_TOKEN = "your_api_token";         
                                        
async function makeRequest(endpoint) {
  const response = await fetch(`${BASE_URL}/${endpoint}`, {                                                                                                          
    headers: {                              
      Authorization: `Bearer ${API_TOKEN}`,                                                                                                                          
      Accept: "application/json",                                  
    },                                                                                                                                                               
  });
                                                                                                                                                                     
  // Read rate limit headers                                       
  const limit = response.headers.get("x-rate-limit-limit");
  const remaining = response.headers.get("x-rate-limit-remaining");
  const reset = response.headers.get("x-rate-limit-reset");

  console.log(`Limit: ${limit}, Remaining: ${remaining}, Reset: ${reset}`);                                                                                          
                                        
  if (response.status === 429) {                                                                                                                                     
    const retryAfter = parseInt(response.headers.get("Retry-After") || "30", 10);                                                                                    
    console.log(`Rate limited. Retrying in ${retryAfter}s...`);
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));                                                                                          
    return makeRequest(endpoint);                                  
  }
                                                                                                                                                                     
  return response.json();
}                                                                                                                                                                    
                                                                   
makeRequest("/users").then(console.log);
```

{% endcode %}
{% endtab %}

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

```ruby
require "net/http"                                                                                                                                                   
require "json"
require "uri"                                                                                                                                                        
                                                                   
BASE_URL = "https://api.woowup.com/apiv3"   
API_TOKEN = "your_api_token"            

def make_request(endpoint)                                                                                                                                           
  uri = URI("#{BASE_URL}/#{endpoint}")
  request = Net::HTTP::Get.new(uri)                                                                                                                                  
  request["Authorization"] = "Bearer #{API_TOKEN}"                 
  request["Accept"] = "application/json"

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|                                                                                        
    http.request(request)               
  end                                                                                                                                                                
                                                                                                                                                                     
  # Read rate limit headers
  limit = response["x-rate-limit-limit"]                                                                                                                             
  remaining = response["x-rate-limit-remaining"]                   
  reset = response["x-rate-limit-reset"]
                                            
  puts "Limit: #{limit}, Remaining: #{remaining}, Reset: #{reset}"

  if response.code.to_i == 429                                                                                                                                       
    retry_after = (response["Retry-After"] || "30").to_i
    puts "Rate limited. Retrying in #{retry_after}s..."                                                                                                              
    sleep(retry_after)                                             
    return make_request(endpoint)
  end                                                                                                                                                                
 
  JSON.parse(response.body)                                                                                                                                          
end                                                                

result = make_request("users")   
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
<?php
                                                                                                                                                                   
$baseUrl = 'https://api.woowup.com/apiv3';                         
$apiToken = 'your_api_token';           

function makeRequest($endpoint) {                                                                                                                                    
  global $baseUrl, $apiToken;
                                                                                                                                                                   
  $ch = curl_init("{$baseUrl}/{$endpoint}");                     
  curl_setopt_array($ch, [            
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HEADERFUNCTION => function ($ch, $header) use (&$headers) {                                                                                          
          $parts = explode(':', $header, 2);
          if (count($parts) === 2) {                                                                                                                               
              $headers[strtolower(trim($parts[0]))] = trim($parts[1]);
          }                                                                                                                                                        
          return strlen($header);     
      },                                                                                                                                                           
      CURLOPT_HTTPHEADER => [                                                                                                                                      
          "Authorization: Bearer {$apiToken}",
          "Accept: application/json",                                                                                                                              
      ],                                                         
  ]);
                                                                                                                                                                   
  $headers = [];
  $body = curl_exec($ch);                                                                                                                                          
  $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);           
  curl_close($ch);                        
                                      
  // Read rate limit headers
  $limit = $headers['x-rate-limit-limit'] ?? 'N/A';                                                                                                                
  $remaining = $headers['x-rate-limit-remaining'] ?? 'N/A';
  $reset = $headers['x-rate-limit-reset'] ?? 'N/A';                                                                                                                
                                                                 
  echo "Limit: {$limit}, Remaining: {$remaining}, Reset: {$reset}\n";                                                                                              

  if ($statusCode === 429) {                                                                                                                                       
      $retryAfter = (int) ($headers['retry-after'] ?? 30);       
      echo "Rate limited. Retrying in {$retryAfter}s...\n";                                                                                                        
      sleep($retryAfter);                                        
      return makeRequest($endpoint);
  }                                                                                                                                                                
                                      
  return json_decode($body, true);                                                                                                                                 
}                                                                                                                                                                    

$result = makeRequest('/users');                                                                                                                                     
                               
```

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

### Authentication <a href="#authentication" id="authentication"></a>

In any call to the API you must sent the apikey in the query string as a parameter.

For example, if your apikey is 'abcdefghijklmnopqrstuvwxyz', you should do a request to

`https://api.woowup.com/apiv3/users?apikey=abcdefghijklmnopqrstuvwxyz`

Other method, and the recomended, is via Authentication Header, in every call you must send the header

`Authorization: Basic abcdefghijklmnopqrstuvwxyz`&#x20;

#### Deleted accounts

Requests from deleted accounts receive `410 Gone` with code `account_deleted`. Once an account has been deactivated, its API key is no longer valid and all requests will\
be rejected.

{% code lineNumbers="true" %}

```json
{
    "payload": [],
    "message": "gone: account deleted",
    "code": "account_deleted"
}
```

{% endcode %}

### Pagination <a href="#pagination" id="pagination"></a>

When you are doing a search, we paginate the results. In all paginated endpoints the pagination's parameters are:

| Parameter | Description                         | Default |
| --------- | ----------------------------------- | ------- |
| limit     | Items per page returned. Max: 100   | 25      |
| page      | Number of the page. First page is 0 | 0       |

### Returned format <a href="#returned-format" id="returned-format"></a>

All endpoints return data in json format, with the `Content-Type: application/json` header. For a correct use you have to send in all the requests the header `Accept: application/json`.

### How to encode 'service\_uid' <a href="#how-to-encode-service_uid" id="how-to-encode-service_uid"></a>

When you are trying to find an user you could identificate this by his id or his service\_uid (commonly is the email), when you use the service\_uid you must encode this in Base64 en the result encode as url safe, for example if you need to do this in php:

```php
<?php

$service_uid = 'example@email.com';
$encoded_uid = urlencode(base64_encode($service_uid));
$url = 'https://api.woowup.com/apiv3/users/'.$encoded_uid.'/exist';

```

### Sample Code: How to start sending us your purchase orders <a href="#sample-code-how-to-start-sending-us-your-purchase-orders" id="sample-code-how-to-start-sending-us-your-purchase-orders"></a>

In the following link you will find a fully functional example in PHP that process a CSV file with orders and customers and use the API to send them to WoowUp: [Download example](https://github.com/woowup/woowup-php-client/blob/master/dist/woowup-php-client-v1.zip)

### Support <a href="#support" id="support"></a>

**Remember to contact us on** [**developers@woowup.com**](mailto:developers@woowup.com) **for any questions, we will be happy to assist you.**
