Назад к блогу

Как обрабатывать конвертацию валют при выплатах международным подрядчикам

V
Vlado Grigirov
August 13, 2026
Currency API Exchange Rates Contractor Payments Multi-Currency Payouts Developer Guide Finexly

Платить разработчику в Лагосе, дизайнеру в Буэнос-Айресе и копирайтеру в Маниле с единого баланса в USD звучит как задача про платежи. На самом деле — нет. Платёжный рельс — давно решённая биржевая услуга. Часть, которая тихо теряет деньги и порождает тикеты в поддержку, — это конвертация валют при выплатах международным подрядчикам: решить, в какой валюте платить, какой обменный курс применить, когда зафиксировать этот курс и как его сохранить, чтобы ваши книги сходились месяцы спустя. Это руководство — для бэкенд-инженера, который владеет кодом выплат и только что получил тикет вроде «сделать так, чтобы подрядчики получали оплату в своей местной валюте».

Ставки реальны и растут. К 2027 году, по оценкам, 86,5 млн человек в США будут фрилансерами, а мировая независимая рабочая сила достигнет 1,57 млрд. При этом скрытые комиссии в трансграничных платежах могут раздуть издержки на 20–40%: одни только SWIFT-переводы добавляют 15–45 USD за платёж плюс валютную наценку 2–4%, а некоторые фриланс-платформы накапливают комиссии до 10%. Большая часть этой маржи прячется в обменном курсе. Если вы сами управляете слоем конвертации с помощью чистого currency API, вы контролируете число, которое важнее всего для ваших подрядчиков — и для вашей финансовой команды.

Почему выплаты подрядчикам — это на самом деле задача о валютных данных

Когда вы отправляете 1000 USD подрядчику, выставляющему счёт в филиппинских песо, происходят три разные вещи: ваша платформа решает, сколько песо представляют эти 1000 USD, платёжный провайдер перемещает деньги, а банк подрядчика зачисляет средства на его счёт. Только средний шаг — это «платёж». Первый шаг — конвертация — это задача о данных, и именно за неё отвечает ваше приложение.

Ошибётесь — и режимы отказа конкретны. Покажите подрядчику в панели оценку выплаты в ₱58 000, а через два дня рассчитайте ₱56 200, потому что курс сдвинулся, — и вы создали проблему доверия. Примените непрозрачный, накрученный курс — и ваши подрядчики рано или поздно сравнят его со среднерыночным курсом и почувствуют, что их понемногу обирают. Не сохраните точный использованный курс — и ваша финансовая команда не сможет сверить пакет выплат с главной книгой в конце месяца. Каждое из этого — решение по обмену валют, которое принимает ваш код, намеренно или случайно.

Три валютных решения, которые должна принять любая система выплат

Прежде чем писать код, сделайте явными три решения. Большинство систем выплат с багами багованы потому, что одно из них было принято неявно.

  1. В какой валюте вы платите? Местная валюта подрядчика (лучший опыт, валютный риск несёте вы), твёрдая валюта вроде USD или EUR (вы перекладываете валюту на его банк, обычно по худшему для него курсу) или стейблкоин. Храните payout_currency на каждого подрядчика, а не предполагайте.
  2. Какой курс вы применяете? Среднерыночный курс — честная точка отсчёта. Поверх него вы можете добавить прозрачную маржу для покрытия спреда провайдера. Чего никогда нельзя делать — применять накрученный курс и называть его «обменным курсом».
  3. Когда вы фиксируете курс? При одобрении счёта, при создании пакета или при исполнении. Промежуток между этими моментами — там, где кусается волатильность. Что бы вы ни выбрали, зафиксированный курс должен быть тем, который вы показываете, по которому рассчитываетесь и который сохраняете.

Строим слой конвертации шаг за шагом

Построим ядро сервиса конвертации выплат. Схема одинакова, платите ли вы одному подрядчику или десяти тысячам: получить надёжный курс, применить прозрачную маржу, вычислить сумму и сохранить использованный курс.

Шаг 1. Получите надёжный среднерыночный курс

Начните с сырого курса. Вот прямой вызов Finexly API через cURL:

curl "https://api.finexly.com/v1/latest?base=USD&symbols=PHP,ARS,NGN&apikey=YOUR_API_KEY"

Типичный ответ:

{
  "base": "USD",
  "timestamp": 1755072000,
  "rates": {
    "PHP": 58.12,
    "ARS": 1287.40,
    "NGN": 1531.75
  }
}

В Python оберните это в маленькую функцию, возвращающую Decimal, с которым можно вести денежную арифметику:

import requests
from decimal import Decimal

API_KEY = "YOUR_API_KEY"

def get_rate(base: str, quote: str) -> Decimal:
    resp = requests.get(
        "https://api.finexly.com/v1/latest",
        params={"base": base, "symbols": quote, "apikey": API_KEY},
        timeout=10,
    )
    resp.raise_for_status()
    return Decimal(str(resp.json()["rates"][quote]))

Для валютной арифметики всегда используйте Decimal, никогда float. Ошибки округления с плавающей точкой невидимы на одной выплате и очень заметны на пакете из 5000.

Шаг 2. Примените прозрачную маржу

Если нужно покрыть спред провайдера, добавьте его как явную, поддающуюся аудиту наценку, а не прячьте внутри курса:

def payout_amount(usd_amount: Decimal, base: str, quote: str,
                  margin_pct: Decimal = Decimal("0.5")) -> dict:
    mid = get_rate(base, quote)
    applied = mid * (1 - margin_pct / 100)     # margin works against the payee
    gross = (usd_amount * applied).quantize(Decimal("0.01"))
    return {
        "mid_market_rate": mid,
        "margin_pct": margin_pct,
        "applied_rate": applied.quantize(Decimal("0.000001")),
        "payout_local": gross,
    }

Возврат среднерыночного курса, маржи и применённого курса по отдельности означает, что подрядчик (или аудитор) всегда может увидеть, как именно построено число. Прозрачность здесь — конкурентное преимущество: это противоположность «комиссий до 10% в сумме», которые отгоняют подрядчиков от непрозрачных платформ.

Шаг 3. Зафиксируйте и сохраните курс

Курс, который вы показываете при одобрении, должен равняться курсу, по которому вы рассчитываетесь. Сохраните его в момент фиксации:

quote = payout_amount(Decimal("1000.00"), "USD", "PHP")
# store alongside the payout record
save_payout(
    contractor_id=4471,
    usd_amount=Decimal("1000.00"),
    payout_currency="PHP",
    applied_rate=quote["applied_rate"],
    mid_market_rate=quote["mid_market_rate"],
    locked_at=datetime.utcnow(),
)

Этот сохранённый applied_rate — самое важное поле в вашей таблице выплат. Именно оно делает выплату проверяемой, именно с ним вы сверяетесь и именно его показываете подрядчику, если он спросит, почему получил ровно эту сумму.

Конвертируем весь платёжный прогон одним пакетом

Платить подрядчикам по одному — значит долбить API и напрашиваться на несогласованность: два подрядчика в одном прогоне получают разные курсы USD/EUR, потому что их запросы ушли с разницей в минуту. Вместо этого получите все нужные курсы одним вызовом, а затем примените их ко всему прогону, чтобы каждая выплата в пакете использовала один и тот же снимок курсов:

from decimal import Decimal
import requests

def batch_convert(payouts: list[dict], base: str = "USD") -> list[dict]:
    symbols = ",".join(sorted({p["currency"] for p in payouts}))
    rates = requests.get(
        "https://api.finexly.com/v1/latest",
        params={"base": base, "symbols": symbols, "apikey": API_KEY},
        timeout=10,
    ).json()["rates"]

    out = []
    for p in payouts:
        rate = Decimal(str(rates[p["currency"]]))
        local = (Decimal(str(p["usd"])) * rate).quantize(Decimal("0.01"))
        out.append({**p, "rate": rate, "local_amount": local})
    return out

run = batch_convert([
    {"contractor_id": 4471, "usd": "1000.00", "currency": "PHP"},
    {"contractor_id": 5522, "usd": "750.00",  "currency": "ARS"},
    {"contractor_id": 6033, "usd": "1200.00", "currency": "NGN"},
])

Один снимок курсов на прогон даёт вам чистую, защитимую историю сверки: каждая выплата в пакете #8821 использовала курсы, захваченные в один момент. Когда вы масштабируетесь до тысяч выплат за цикл, эта схема также удерживает вас с запасом внутри разумных лимитов запросов — посмотрите тарифные планы, чтобы узнать поддерживаемые объёмы запросов на каждом уровне.

Обработка волатильности между одобрением и исполнением

Опасный промежуток — это время между тем, когда вы обещаете сумму, и тем, когда деньги реально движутся. В быстрых валютах это окно может сдвинуть выплату на процентный пункт или больше. Три защитимые стратегии:

  • Фиксация при одобрении. Захватите курс при одобрении выплаты и соблюдайте его при исполнении, поглощая мелкие движения сами. Лучший опыт для подрядчика; валютный риск несёте вы.
  • Фиксация при исполнении. Вычислите сумму в момент выплаты. Вы не несёте риска, но итоговая сумма подрядчика может отличаться от оценки, которую он видел.
  • Фиксация с полосой допуска. Зафиксируйте при одобрении, но перепроверьте при исполнении; если курс сдвинулся больше чем, скажем, на 1,5%, пометьте выплату на проверку, а не рассчитывайте молча другую сумму.

Быстрая проверка допуска на JavaScript:

async function withinTolerance(currency, lockedRate, tolerancePct = 1.5) {
  const res = await fetch(
    `https://api.finexly.com/v1/latest?base=USD&symbols=${currency}&apikey=YOUR_API_KEY`
  );
  const { rates } = await res.json();
  const drift = Math.abs((rates[currency] - lockedRate) / lockedRate) * 100;
  return { ok: drift <= tolerancePct, drift: drift.toFixed(2) };
}

Какую бы модель вы ни выбрали, задокументируйте её в договоре с подрядчиком, чтобы задать ожидания до того, как кто-то оспорит число.

Сохраняйте использованный курс: сверка и комплаенс

Через недели после выплаты кому-то из финансов придётся ответить: «по какому курсу мы заплатили подрядчику 4471 6 августа?» — или подрядчик запросит свою сумму. Если вы сохранили только местную сумму, вы не восстановите ответ. Если сохранили курс — восстановите, и вдобавок сможете проверить его по независимому источнику через исторический эндпойнт:

curl "https://api.finexly.com/v1/historical?date=2026-08-06&base=USD&symbols=PHP&apikey=YOUR_API_KEY"

Это та же дисциплина, что управляет трансграничным начислением зарплаты и выплатами маркетплейса: курс — это финансовые данные первого класса, а не одноразовое промежуточное значение. Храните для каждой выплаты базовую валюту, валюту выплаты, среднерыночный курс, маржу, применённый курс и метку времени фиксации. Все детали API — в документации Finexly API.

Частые ошибки, которых стоит избегать

  • Использование float для денег. Дрейф округления накапливается по пакету. Используйте десятичные числа с фиксированной точкой везде.
  • Получение курсов на каждую выплату в цикле. Несогласованные курсы внутри прогона и лишняя нагрузка на API. Берите один снимок на пакет.
  • Прятать маржу внутри курса. Подрядчики её обнаружат. Показывайте среднерыночный курс и маржу по отдельности.
  • Не сохранять применённый курс. Вы теряете возможность сверить или объяснить выплату задним числом.
  • Игнорировать промежуток между одобрением и исполнением. В волатильных валютах это тихо меняет то, что получают подрядчики. Фиксируйте намеренно.
  • Предполагать, что каждый подрядчик хочет местную валюту. Некоторые предпочитают USD или стейблкоин. Храните предпочтение на каждого подрядчика.

Часто задаваемые вопросы

Какой обменный курс использовать для оплаты международным подрядчикам? Отталкивайтесь от среднерыночного курса — настоящей середины между ценами покупки и продажи — как от честной опоры. Если нужно покрыть издержки провайдера, добавьте небольшую, явно раскрытую маржу сверху, а не раздувайте сам курс. Подрядчики доверяют прозрачной математике куда больше, чем единственному непрозрачному числу.

Платить подрядчикам в их местной валюте или в USD? Оплата в местной валюте даёт подрядчику лучший опыт, потому что он точно знает, что придёт на счёт, но означает, что валютную конвертацию несёт ваша платформа. Оплата в USD перекладывает конвертацию на его банк, который обычно даёт ему худший курс. Лучшие системы хранят предпочтение валюты на каждого подрядчика и поддерживают оба варианта.

Как сохранить сумму выплаты согласованной в большом пакете? Получите все нужные валютные курсы одним вызовом API в начале прогона, а затем примените этот единственный снимок к каждой выплате. Это гарантирует, что два подрядчика в одном прогоне получат один и тот же курс USD-EUR, и даёт вам единственную метку времени для сверки.

Как избежать скрытых комиссий, раздувающих выплаты подрядчикам на 20–40%? Большая часть этого раздувания живёт в валютной наценке и в сборах за перевод. Владение слоем конвертации с прозрачным источником курсов позволяет показать подрядчикам среднерыночный курс и ровно ту маржу, если она есть, которую вы применяете, — вместо наценок 2–4% на переводы и платформенных комиссий до 10%, встроенных во многие готовые инструменты.

Какие данные хранить по каждой выплате подрядчику? Как минимум: базовую валюту, валюту выплаты, среднерыночный курс, любую применённую маржу, итоговый применённый курс, местную сумму и метку времени, когда вы зафиксировали курс. Именно эта запись делает выплату проверяемой и сверяемой месяцы спустя.

Готовы построить слой конвертации выплат, которому доверяют и ваши подрядчики, и ваши аудиторы? Получите бесплатный ключ Finexly API — без кредитной карты. Начните с 1000 бесплатных запросов в месяц, получайте курсы в реальном времени и исторические для более чем 170 валют и масштабируйтесь по мере роста объёма выплат. Вы также можете попробовать быструю конвертацию в нашем конвертере валют, чтобы увидеть данные из первых рук.

Vlado Grigirov

Senior Currency Markets Analyst & Financial Strategist

Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...

View full profile →