Использование API

Постбэк

Параметры в ссылке
    &web_id       - айди вебмастера в вашей системе (если она есть); максимальная длина 100 символов.
    &sub1         - дополнительные данные в произвольном формате; максимальная длина 100 символов.
    &sub2         - дополнительные данные в произвольном формате; максимальная длина 100 символов.
    &sub3         - дополнительные данные в произвольном формате; максимальная длина 100 символов.
    &sub4         - дополнительные данные в произвольном формате; максимальная длина 100 символов.
    &sub5         - дополнительные данные в произвольном формате; максимальная длина 100 символов.
    &utm_source   - максимальная длина 100 символов.
    &utm_medium   - максимальная длина 100 символов.
    &utm_campaign - максимальная длина 100 символов.
    &utm_content  - максимальная длина 100 символов.
    &utm_term     - максимальная длина 100 символов.
                    
    При поступлении заказа в систему и при изменении его статуса наша система может оповещать стороннюю систему,
    отправляя HTTP-запрос.
    Запрос может быть отправлен методом POST или GET (согласно настройкам в профиле),
    но данные передаются в URL (соответственно, ловятся в $_GET).

    Наша система будет отправлять постбэк в течение недели, до тех пор, пока в ответ не получит
    HTTP-статус 200.

    Постбэк срабатывает максимум 3 раза - при создании нового заказа, при смене статуса на confirmed, holded, cancelled
    или trash и переходе из holded в confirmed.

    Глобальные URL-ы постбэков указывается в админке Traffic Light на странице профиля.
    Также можно указать постбэки для каждого потока индивидуально.

    Для каждого статуса URL можно указать отдельно; если URL не указан для "trash" то будет использоваться URL для
    "cancelled".

    Если для confirmed или cancelled URL не указан то по этим статусам не будет постбэка.

    Информация о попытках отправки постбэков хранится в течение 30 дней.

    В URL можно вставить макросы:
      {id}                  - id заказа в нашей системе
      {id2}                 - id заказа в нашей системе (если заказ пришел к нам по API)
      {created_at}          - время создания заказа в ISO-формате (например, '2015-06-12T17:50:39+00:00'), всегда в UTC
      {created_at_unixtime} - время создания заказа в виде POSIX timestamp (например, 1434131439)
      {status}              - возможные варианты new|cancelled|holded|confirmed
      {status_code}         - возможные варианты 0|-10|5|10
      {status_id}           - 2 - новый, 1 - подтверждён, 4 - подтверждён в холде, 3 - отменён
      {payout}              - начисление вебмастеру за заказ
      {payout_currency}     - валюта начисления вебмастеру за заказ (например, 'RUB', 'USD' или 'EUR')
      {offer_id}            - id оффера в нашей системе
      {country}             - страна заказчика (например, 'RU')
      {ip_address}          - IP-адрес заказчика (например, '176.59.124.152')

      {trash}               - числовой код, если треш
      {comment}             - комментарий (как правило, в случае отказа); может быть пустым, если коллцентр не предоставляет комментарии отказов
                              * в случае треша это будет описание треша

      {sub1}                - из соответствующего параметра в ссылке
      {sub2}                - из соответствующего параметра в ссылке
      {sub3}                - из соответствующего параметра в ссылке
      {sub4}                - из соответствующего параметра в ссылке
      {sub5}                - из соответствующего параметра в ссылке
      {web_id}              - из соответствующего параметра в ссылке

      {utm_source}          - из соответствующего параметра в ссылке
      {utm_medium}          - из соответствующего параметра в ссылке
      {utm_campaign}        - из соответствующего параметра в ссылке
      {utm_content}         - из соответствующего параметра в ссылке
      {utm_term}            - из соответствующего параметра в ссылке

      {fee}                 - то же, что "payout" (устаревшее)
      {subaccount}          - то же, что "sub1" (устаревшее)
      {ex}                  - то же, что "sub2" (устаревшее)
      {extra}               - то же, что "sub2" (устаревшее)

      Статус (status):
      new - в обработке
      cancelled - отменен
      holded - подтвержден в холде
      confirmed - подтвержден

      Код статуса (status_code):
      0 - в обработке
      -10 - отменен
      5 - подтвержден в холде
      10 - подтвержден

    Пример URL-а постбэка:

    http://example.com/api/orders/postback/?o={id}&click_id={sub1}&offer={offer_id}&money={payout}&s={status}

                    

Приемник лидов

      POST http://api.cpa.tl/api/lead/send

      На данный URL методом POST отправляется запрос, в теле сообщения передаются данные:

        "key": string                       - ключ доступа к API, получите в профиле  https://cpa.tl/u/profile
        "id": string                          - id лида в вашей системе
        "offer_id": int                    - id оффера в нашей системе
        "stream_hid": string        - id потока в нашей системе
        "ip_address": string         - ip address лида
        "name": sting                     - ФИО покупателя
        "phone": string                 - телефон покупателя
        "comments": string          - комментарии к заказу
        "country": string               - страна покупателя
        "address":string                - адрес покупателя
        "tz": int                                - временная зона, например 3 для Europe/Moscow (как получить тайм зону?)
        "web_id": string                - id вебмастера в вашей системе
        "email": string                   - email покупателя
        "ip_address": string
        "user_agent": string

        "utm_source": string(100)
        "utm_medium": string(100)
        "utm_campaign": string(100)
        "utm_content": string(100)
        "utm_term": string(100)

        "sub1": string(255)
        "sub2": string(255)
        "sub3": string(255)
        "sub4": string(255)
        "sub5": string(255)

      в случае успеха, ответ будет HTTP 200, в формате json, и будет содержать данные:
      "id" - id лида в нашей системе;
      "autologin_url" (необязательно) - ссылка на авто-логин сайта брокера, если категория оффера, поддерживает данный признак;
      "error" (необязательно) - сообщение об ошибке, если не удалось успешно отправить заявку рекламодателю.
      Примеры успешного ответа:
          {"id": 123}
          {"id": 123, "autologin_url": "https://example.click?token=kfjdgksjd"}
      Пример ответа c ошибкой:
          {"id": 123, "autologin_url": "", "error": "Lead sending error to the advertiser"}
      обязательные поля:
      key, offer_id, phone, country, ip_address

      так же для дополнительного контроля трафика очень желательно указать:
      name, web_id, user_agent

    В случае ошибки будет отправлен ответ HTTP 409, в формате json содержать статус ошибки, например:
    {"errmsg": "country is a required field"}

    Возможные статусы ошибок
    offer not found                                     - оффер не найден или нет гео совпадающего с переданным в country
    incorrect IP-address                            - не корректный IP-address
    country is a required field                 - поле country (страна) обязательно для сохранения заявки
    incorrect country code; should be ISO2 or ISO3 format - не корректный код страны передаваемый в поле country
    customer phone is a required field - поле phone (телефон) обязательно для сохранения заявки
    incorrect customer phone                  - не корректный номер телефона
    customer name too long                    - поле name (имя) слишком длинное
    wrong tz {}                                               - поле tz (таймзона) не верный формат
    incorrect timezone                               - поле tz (таймзона) не верный формат
    duplicate order [ {} ]                             - дубль заявки
    

Пример на php ( скачать ):

        <?php

        $apiKey = 'xxxxxxxxxxxxxxxxxxxxxxx';
        $offer_id = 0; // для каждого оффера свой айди, надо уточнять его в админке или у суппортов
        $stream_hid = ''; // не обязательное, если указано, заявка будет привязана к потоку
        $apiUrl = 'http://api.cpa.tl/api/lead/send';

        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $data_post = $_POST;

            $data = array(
                    'key' => $apiKey,
                    'id' => microtime(true), // тут лучше вставить значение, по которому вы сможете идентифицировать свой лид; можно оставить microtime если у вас нет своей crm
                    'offer_id' => $offer_id,
                    'stream_hid' => $stream_hid,
                    'name' => $data_post['name'],
                    'phone' => $data_post['phone'],
                    'comments' => $data_post['comments'],
                    'country' => $data_post['country'], // формат ISO 3166-1 Alpha-2 - https://ru.wikipedia.org/wiki/ISO_3166-1
                    'address' => $data_post['address'],
                    'tz' => $data_post['timezone_int'], // очень желательно получать его с ленда, но если никак лучше оставить пустым или 3 (таймзона мск)
                    'web_id' => '',
                    'ip_address' => isset($_SERVER["HTTP_CF_CONNECTING_IP"]) ? $_SERVER["HTTP_CF_CONNECTING_IP"] : $_SERVER['REMOTE_ADDR'],
                    'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            );

            $options = array(
                    'http' => array(
                        'header' => "Content-type: application/x-www-form-urlencoded\r\n",
                        'method' => 'POST',
                        'content' => http_build_query($data),
                        'ignore_errors' => true,
                    )
            );

            $context = stream_context_create($options);
            $result = file_get_contents($apiUrl, false, $context);

            $obj = json_decode($result);

            if (null === $obj) {
                    // Ошибка в полученном ответе
                    print("Invalid JSON");
                } else if (!empty($obj->errmsg)) {
                    // Ошибка в отправленном запросе
                    print("Ошибка: " . $оbj->errmsg);
                } else {
                    print('ID заявки: ' . $obj->id);
            }

        }

        
Пример на Python ( скачать ):
    import time
    import requests

    API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxx'
    API_URL = 'http://api.cpa.tl/api/lead/send'
    offer_id = 0    # id оффера в нашей системе, для каждого оффера свой айди, надо уточнять его в админке или у суппортов
    stream_hid = '' # не обязательное, если указано, заявка будет привязана к потоку

    data = {
        'key': API_KEY,
        'id': int(round(time.time() * 1000)),    # тут лучше вставить значение, по которому вы сможете идентифицировать свой лид
        'offer_id': offer_id,  # для каждого оффера свой айди, надо уточнять его в админке или у суппортов
        'stream_hid': stream_hid,
        'name': 'tester (отклонить)',
        'phone': '8 999 1111122',
        'comments': 'test lead',
        'country': 'RU', # формат ISO 3166-1 Alpha-2 - https://ru.wikipedia.org/wiki/ISO_3166-1
        'address': '',
        'tz': 3,  # очень желательно получать его с ленда, но если никак лучше оставить пустым или 3 (таймзона мск)
        'web_id': '',
        'ip_address': '194.58.117.14',   # ip с которого получена заявка. в Django можно получить request.META.get('REMOTE_ADDR')
        'user_agent': '',   # в Django можно получить HTTP_USER_AGENT
    }


    r = requests.post(API_URL, data=data)
    if r.status_code == 200:
        lead_id = r.json().get('id')
        print('ID заявки: {}'.format(lead_id))
    elif r.status_code == 404:
        print('проверьте API_KEY, API_URL, offer_id')
    elif r.status_code == 409:
        err_mess = r.json().get('errmsg')
        print(err_mess)

    

Как получить таймзону :

    Тайм зону клиента можно получить с помощью javascript и передать в скрытое поле в форме

    <input id="tz" name="timezone_int" type="hidden" value="" />

    <script>
        $(document).ready(function () {
            $("#tz").val(new Date().getTimezoneOffset() / -60);
        });
    </script>
    

Фид лидов

    GET http://api.cpa.tl/api/lead/feed?key=<key>&[filters]

      возвращает список лидов в формате json.

      <key> - ключ доступа к API, получите в профиле https://cpa.tl/u/profile

      возможные фильтры:
       - id  - искать по id лида в нашей системе
       - id2 - искать по id лида в вашей системе
       - offset - сдвиг выгрузки (если не указано = 0)

      проверить несколько лидов одновременно можно указав несколько id или id2, например
         - id2[]=1&id2[]=2&id2[]=3&id2[]=N

       - date - если указано 1 значение - будут лиды за эту дату; если 2 - все лиды за указанный
         период (дата "до" не попадает в выборку). Например:
         - date=2024-06-01 - вернёт лиды за 1 июня 2024
         - date[]=2024-06-01&date[]=2024-07-01 - вернёт лиды за июнь
       - date_to_with - при true дата "до" будет включена в выборку. Например:
         - date[]=2024-06-01&date[]=2024-06-30&date_to_with=true - вернёт лиды за июнь
       - by_status_changed_at - при true значении параметра фильтрация будет производиться по дате
         последнего изменения статуса, а не по дате создания.

      Описание ответа:
        count - количество лидов в ответе
        total - общее количество лидов по запрашиваемым фильтрам
        offset - сдвиг в текущей выгрузке
        limit - запрашиваемое количество лидов
        leads - список лидов

      Описание полей лидов:
        "status_code": int          - 0 - новый, 10 - подтверждён, 5 - подтверждён в холде, -10 - отменён
        "status": string                    - "new" - новый, "confirmed" - подтверждён, "holded" - подтверждён в холде, "cancelled" - отменён
        "status_id": int            - 2 - новый, 1 - подтверждён, 4 - подтверждён в холде, 3 - отменён
        "trash": int or null       - числовой код, если треш
        "comment": string or null          - комментарий (например, 'недозвон'), как правило, в случае отказа; может быть пустым, если коллцентр не предоставляет комментарии отказов
                                              * в случае треша это будет описание треша
        "payout": string                    - начисление вебмастеру за заказ (например, '500.00' или '90')
        "payout_currency": string           - валюта начисления вебмастеру за заказ (например, 'RUB', 'USD' или 'EUR')
        "created_at": string                - время создания заказа в ISO-формате (например, '2015-06-12T17:50:39+00:00'), всегда в UTC
        "created_at_unixtime": int  - время создания заказа в виде POSIX timestamp (например, 1434131439)
        "id": 43179                         - id лида/заказа в нашей системе
        "id2": 205                          - id лида/заказа в вашей системе (может быть null)
        "offer_id": 5                       - id оффера в нашей системе
        "country": string                   - страна заказчика (например, 'RU')
        "ip_address": string                - IP-адрес заказчика (например, '176.59.124.152')
        "order_page": string                - URL-адрес страницы заказа

        "utm_source"                        - значение, указанное при создании лида
        "utm_medium"                        - значение, указанное при создании лида
        "utm_campaign"                      - значение, указанное при создании лида
        "utm_content"                       - значение, указанное при создании лида
        "utm_term"                          - значение, указанное при создании лида
        "web_id"                            - значение, указанное при создании лида

        "sub1"                              - значение, указанное при создании лида
        "sub2"                              - значение, указанное при создании лида
        "sub3"                              - значение, указанное при создании лида
        "sub4"                              - значение, указанное при создании лида
        "sub4"                              - значение, указанное при создании лида

        "fee"                               - то же, что "payout" (устаревшее)
        "subaccount"                        - то же, что "sub1" (устаревшее)
        "ex"                                - то же, что "sub2" (устаревшее)
        "extra"                             - то же, что "sub2" (устаревшее)
        "trash_reason"                      - то же, что "trash" (устаревшее)
    

Пример на php ( скачать ):

    <?php

    $apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
    $apiUrl = 'http://api.cpa.tl/api/lead/feed';

    $data = array(
        'key' => $apiKey,

        // настраиваем фильтры, можно использовать как один так и несколько фильтров
        // получаем данные по id в нашей системе
        'id' => ['xxxxxx', 'xxxxxx'],

        // получаем данные по id в вашей системе
        //'id2' => ['xxxxxx', 'xxxxxx'],

        // получаем все заявки по заданной дате
        //'date' => ['2018-07-01', '2018-07-15'],

    );

    function http_build_query_noindex($a, $b=0, $c=0){
        if (!is_array($a)) { return false; }
        foreach ((array)$a as $k=>$v){
            if ($c) { $k = $b."[]"; }
            elseif (is_int($k)) { $k = $b . $k; }
            if (is_array($v)||is_object($v)) {
                $r[]=http_build_query_noindex($v, $k, 1);
                continue;
            }
            $r[] = urlencode($k) . "=" . urlencode($v);
        }
        return implode("&", $r);
    }

    $result = file_get_contents($apiUrl.'?'.http_build_query_noindex($data, ''));

    $obj = json_decode($result);

     if (null === $obj) {
        // Ошибка в полученном ответе
        echo "Invalid JSON";
    } elseif (!empty($jsonObj->errmsg)) {
        // Ошибка в отправленном запросе
        echo "Ошибка: " . $jsonObj->errmsg;
    } else {
        print('Получено заявок: ' . $obj->count . " \n
"); foreach ($obj->leads as $lead) { print($lead->id . ' - ' . $lead->status. " \n
"); } }
Пример на Python ( скачать ):
    import datetime
    import requests

    API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxx'
    API_URL = 'http://api.cpa.tl/api/lead/feed'

    data = {
        'key': API_KEY,
        # формируем фильтры
        # 'id': 'xxxxxx', # получаем данные об одной заявке по id в нашей системе
        # 'id': ['xxxxxx', 'xxxxxx', ], # получаем данные по нескольким заявкам по id в нашей системе
        # 'id2': 'xxxxxx',   # получаем данные по одной заявке по id в вашей системе
        # 'id2': ['xxxxxx', 'xxxxxx', ], # получаем данные по нескольким заявкам по id в нашей системе
        # 'date': '2018-07-15', # получаем все заявки по заданной дате
        # 'date': datetime.date.today().strftime('%Y-%m-%d'),  # получаем заявки за сегодня
        'date': ['2018-07-01', '2018-07-15', ],   # получаем заявки с 1 по 15 июля 2018 года
    }

    r = requests.get(API_URL, params=data)

    if r.status_code == 200:
        data = r.json()
        print('получено {} заявок'.format(data.get('count')))

        for lead in data.get('leads'):
            lead_id = lead.get('id2')   # id лида в вашей системе
            status_code = lead.get('status')

            if status_code == 'new':
                status = 'новый'
            elif status_code == 'confirmed':
                status = 'подтвержден'
            elif status_code == 'new|cancelled':
                status = 'отменен'
            else:
                status = '--'
            print('Заявка {} статус {}'.format(lead_id, status))

    elif r.status_code == 404:
        print('проверьте API_KEY, API_URL, offer_id')
    elif r.status_code == 409:
        err_mess = r.json().get('errmsg')
        print(err_mess)

    

Баланс

    GET http://api.cpa.tl/api/user/balance?key=<key>

      возвращает баланс по всем валютам в формате json.

      <key> - ключ доступа к API, получите в профиле https://cpa.tl/u/profile

      описание ответа:
        currency - валюта, может принимать значения: 'RUB', 'USD', 'EUR', 'COIN'

        {
            currency: {
                "total": 0,         - всего заработано
                "payment": 0,       - выплачено
                "earn": 0,          - начислено
                "hold": 0,          - в холде
                "balance": 0,       - на балансе
            }
        }