API نرخ همکاران همتا گیفت
با این API، وبسایت، فروشگاه اینترنتی یا ربات شما نرخهای حساب همکاری خودتان را مستقیماً از همتا گیفت دریافت میکند؛ بدون ورود دستی قیمت و همیشه همزمان با پنل همکاران.
معرفی
API همتا گیفت یک سرویس REST فقطخواندنی است که پاسخ را در قالب JSON و با کدگذاری UTF-8 برمیگرداند. هر کلید API به یک حساب همکاری تعلق دارد و فقط نرخهای همان حساب را برمیگرداند: بهای تمامشده شما از همتا گیفت و قیمت مشتری شما با حاشیه سودی که خودتان در پنل همکاران تعیین کردهاید. نرخ مرجع بازار در این API ارائه نمیشود.
https://hamtagift.com
همه درخواستها باید از طریق HTTPS ارسال شوند.
احراز هویت
هر درخواست باید کلید API را در سرآیند Authorization و به شکل Bearer ارسال کند. کلیدها با پیشوند hamta_live_ شروع میشوند.
- وارد پنل همکاران شوید و صفحه «API و تلگرام» را باز کنید.
- یک کلید جدید بسازید (نقشهای مالک، مدیر و توسعهدهنده امکان ساخت کلید دارند).
- کلید فقط یک بار نمایش داده میشود؛ آن را در یک متغیر محیطی امن روی سرور خود نگه دارید. همتا گیفت فقط نسخه رمزنگاریشده کلید را ذخیره میکند؛ اگر کلید را گم کردید، آن را باطل کنید و کلید جدید بسازید.
Authorization: Bearer hamta_live_…کلید API را هرگز در کد سمت مرورگر (JavaScript صفحه)، اپلیکیشن موبایل یا مخزن کد عمومی قرار ندهید. درخواست را فقط از سرور خود ارسال کنید.
دریافت نرخها
نرخهای فعلی ابزارهای حساب همکاری شما را برمیگرداند: همه آنها، یا فقط ابزارهایی که با پارامتر اختیاری instruments نام میبرید. این درخواست بدنه ندارد و پاسخ آن هرگز کش نمیشود (Cache-Control: no-store).
پارامتر اختیاری instruments
برای دریافت فقط برخی ابزارها، instruments= را با کدهای آنها از جدول «ابزارها»، جداشده با ویرگول انگلیسی (,)، به آدرس اضافه کنید. حروف بزرگ و کوچک در کدها فرقی ندارد (rub همان RUB است)؛ فاصلهها و کدهای تکراری نادیده گرفته میشوند و فهرست rates با هر ترتیبی که کدها را بفرستید، به ترتیب جدول «ابزارها» برمیگردد. بدون این پارامتر یا با مقدار خالی، همه ابزارها برمیگردند. اگر حتی یک کد ناشناخته باشد، هیچ نرخی برنمیگردد: پاسخ 400 با کد unknown_instruments است، کدهای ناشناخته در invalid و همه کدهای معتبر در allowed. این پارامتر پس از بررسی کلید، IP، سقف دقیقهای و ساعات بازار بررسی میشود؛ پس درخواست ردشده هم در سقف دقیقهای شمرده میشود.
GET /api/partner/v1/rates?instruments=dollar,euro{
"ok": false,
"error": "unknown_instruments",
"invalid": [
"<string>"
],
"allowed": [
"havaleLir",
"dollar",
"euro",
"usdtToLir",
"AMD_1000",
"usdtPrice",
"AFN",
"onlineShop",
"sipay",
"RUB"
]
}ساعات و دسترسی
API نرخها در روزهای کاری بازار از ساعت ۱۱:۰۰ تا ۲۰:۰۰ به وقت تهران پاسخ میدهد (آخرین درخواست پذیرفتهشده ساعت ۱۹:۵۹). جمعهها و روزهای تعطیل رسمی بازار بسته است. خارج از این ساعات پاسخ 503 با کد OUTSIDE_MARKET_HOURS برمیگردد؛ سرآیند Retry-After تعداد ثانیه تا بازگشایی بعدی و فیلد next_open زمان آن را (ISO 8601، UTC) نشان میدهد.
{
"ok": false,
"success": false,
"error": "OUTSIDE_MARKET_HOURS",
"message": "<string>",
"market_hours": "11:00 - 20:00 Asia/Tehran",
"next_open": "<ISO 8601 string>"
}فهرست IP مجاز اختیاری است و به درخواست شما توسط پشتیبانی همتا گیفت ثبت میشود. تا وقتی آدرسی ثبت نشده باشد، کلیدهای شما از هر IP پذیرفته میشوند. اگر یک یا چند آدرس ثبت شود، هر درخواست از آدرس دیگر با 403 و کد IP_NOT_ALLOWED رد میشود. فقط آدرسهای دقیق و عمومی IPv4 یا IPv6 پذیرفته میشوند (بدون بازه)، حداکثر ۱۰ آدرس؛ این فهرست برای همه کلیدهای حساب شما اعمال میشود و در پنل همکاران (بخش API و تلگرام) قابل مشاهده است.
{
"ok": false,
"success": false,
"error": "IP_NOT_ALLOWED",
"message": "<string>"
}ساختار پاسخ
پاسخ موفق با کد وضعیت 200 برمیگردد. ساختار زیر دقیقاً همان کلیدهایی است که API برمیگرداند؛ به جای مقادیر عددی، نوع داده نوشته شده است. برای دیدن پاسخ واقعی حساب خودتان، صفحه «API و تلگرام» در پنل همکاران را ببینید.
{
"ok": true,
"partner": "<string>",
"updatedAt": "<ISO 8601 string | null>",
"note": "buy = customer buys (خرید از ما), sell = customer sells (فروش به ما). null = not configured.",
"rates": [
{
"code": "havaleLir",
"label": "لیر حواله ترکیه",
"unit": "TOMAN",
"unitBasis": 1,
"partnerCost": {
"retail": {
"buy": "<decimal string | null>",
"sell": "<decimal string | null>"
},
"wholesale": {
"buy": "<decimal string | null>",
"sell": "<decimal string | null>"
}
},
"customerPrice": {
"retail": {
"buy": "<decimal string | null>",
"sell": "<decimal string | null>"
},
"wholesale": {
"buy": "<decimal string | null>",
"sell": "<decimal string | null>"
}
}
},
…
]
}شرح فیلدها
| فیلد | نوع | توضیح |
|---|---|---|
ok | boolean | در پاسخ موفق همیشه true و در پاسخ خطا false است. |
partner | string | نام شرکت شما، همانطور که در حساب همکاری ثبت شده است. |
updatedAt | string | null | زمان آخرین بهروزرسانی نرخهای مرجع همتا گیفت به قالب ISO 8601 (UTC)؛ اگر مشخص نباشد null است. |
note | string | یادداشت ثابت درباره معنای buy، sell و null. |
rates | array | فهرست ابزارها (همه، یا آنهایی که در instruments نام بردهاید)، همیشه به ترتیب جدول «ابزارها». |
rates[].code | string | شناسه ثابت ابزار؛ در کد خود به این فیلد تکیه کنید، نه به label. |
rates[].label | string | نام فارسی ابزار برای نمایش؛ ممکن است تغییر کند. |
rates[].unit | "TOMAN" | "TRY" | واحد قیمت: TOMAN یعنی تومان، TRY یعنی لیر ترکیه. |
rates[].unitBasis | integer | قیمت برای این تعداد واحد است؛ مثلاً 1000 یعنی قیمت هر ۱۰۰۰ واحد. |
rates[].partnerCost | { retail, wholesale } | بهای تمامشده شما از همتا گیفت، به تفکیک سطح خرده (retail) و عمده (wholesale). |
rates[].customerPrice | { retail, wholesale } | قیمت مشتری شما: بهای تمامشده بهعلاوه حاشیه سودی که خودتان در پنل همکاران تعیین کردهاید (پیشفرض ۱٪). در کمپین تخفیف این حاشیه میتواند تا ۲٪- باشد؛ آنوقت قیمت مشتری از بهای تمامشده شما بهتر است. اگر برای آن جهت حاشیهای تعیین نشده باشد null است. |
….buy | string | null | قیمتی که مشتری از شما میخرد (خرید از ما). |
….sell | string | null | قیمتی که مشتری به شما میفروشد (فروش به ما). |
همه قیمتها رشته عددی اعشاری (تا ۶ رقم اعشار) یا null هستند. null یعنی «تنظیم نشده»؛ هرگز آن را صفر در نظر نگیرید.
ابزارها
بدون پارامتر instruments، فهرست rates شامل همه این ابزارها با همین ترتیب است:
| code | ابزار | unit | unitBasis |
|---|---|---|---|
havaleLir | لیر حواله ترکیه (تومان برای هر لیر) | TOMAN | 1 |
dollar | دلار آمریکا (تومان برای هر دلار) | TOMAN | 1 |
euro | یورو (تومان برای هر یورو) | TOMAN | 1 |
usdtToLir | لیر ترکیه برای هر USDT | TRY | 1 |
AMD_1000 | درام ارمنستان (تومان برای هر ۱۰۰۰ درام) | TOMAN | 1000 |
usdtPrice | تومان برای هر USDT | TOMAN | 1 |
AFN | افغانی افغانستان (تومان برای هر افغانی) | TOMAN | 1 |
onlineShop | لیر آنلاین شاپ (تومان برای هر لیر) | TOMAN | 1 |
sipay | لیر همتاکارت (تومان برای هر لیر) | TOMAN | 1 |
RUB | روبل روسیه (تومان برای هر روبل) | TOMAN | 1 |
خطاها
خطاهای API بهصورت JSON با "ok": false و یک کد در "error" برمیگردند. خطاهای IP_NOT_ALLOWED و OUTSIDE_MARKET_HOURS علاوه بر آن "success": false و یک "message" به زبان سرآیند Accept-Language شما دارند (fa، en، tr، hy؛ در غیر این صورت انگلیسی). دو پاسخ آخر جدول از لایه امنیتی سایت میآیند و متن ساده هستند، نه JSON.
| وضعیت | error | معنا | اقدام پیشنهادی |
|---|---|---|---|
401 | missing_or_malformed_token | سرآیند Authorization ارسال نشده یا کلید با قالب hamta_live_ نیست. | سرآیند را به شکل Bearer و با کلید کامل ارسال کنید. |
401 | invalid_token | کلید شناختهشده نیست، باطل شده یا حساب همکاری فعال نیست. | در پنل همکاران کلید جدید بسازید یا با همتا گیفت تماس بگیرید. |
403 | IP_NOT_ALLOWED | کلید معتبر است، اما درخواست از آدرسی خارج از فهرست IP مجاز حساب شما آمده است. | از یک آدرس ثبتشده درخواست بفرستید یا برای تغییر فهرست با پشتیبانی همتا گیفت هماهنگ کنید. |
429 | rate_limited | بیش از ۶۰ درخواست در یک دقیقه با این کلید. | به اندازه سرآیند Retry-After (ثانیه) صبر کنید و نتیجه را کش کنید. |
503 | OUTSIDE_MARKET_HOURS | خارج از ساعات بازار (۱۱:۰۰ تا ۲۰:۰۰ به وقت تهران) یا روز تعطیل بازار. | تا زمان Retry-After یا next_open صبر کنید و آخرین نرخهای معتبر خود را نمایش دهید. |
400 | unknown_instruments | پارامتر instruments کدی دارد که وجود ندارد. | فقط کدهای فهرست allowed یا جدول «ابزارها» را بفرستید. |
503 | rates_unavailable | نرخها موقتاً در دسترس نیستند. | آخرین نرخهای معتبر خود را نگه دارید و بعداً دوباره تلاش کنید. |
403 | — | درخواست توسط قواعد امنیتی سایت رد شد (متن ساده Forbidden). | اگر درخواست شما عادی است، با پشتیبانی همتا گیفت تماس بگیرید. |
429 | — | تعداد درخواستها از یک IP بیش از حد مجاز است (متن ساده). | به اندازه Retry-After صبر کنید و فاصله درخواستها را بیشتر کنید. |
محدودیتها
- حداکثر ۶۰ درخواست در دقیقه برای هر کلید API.
- درخواستها فقط در روزهای کاری بازار، از ۱۱:۰۰ تا ۲۰:۰۰ به وقت تهران پاسخ داده میشوند (بخش «ساعات و دسترسی»).
- درخواستهایی که بهدلیل فهرست IP مجاز رد میشوند از سهمیه دقیقهای کلید شما کم نمیکنند.
- علاوه بر آن، هر آدرس IP برای کل سایت محدودیت درخواست جداگانهای دارد (حداکثر حدود ۲ درخواست در ثانیه بهطور پیوسته).
- فقط روش GET پشتیبانی میشود.
نمونه کد آماده
نمونههای زیر کلید را از متغیر محیطی HAMTA_API_KEY میخوانند، خطاها را بررسی میکنند و قیمت خردهفروشی مشتری را برای هر ابزار چاپ میکنند. نمونه PHP برای فروشگاههای اینترنتی مانند ووکامرس یا لاراول مناسب است.
<?php
// Server side only: never send the API key to the browser.
$apiKey = getenv('HAMTA_API_KEY'); // hamta_live_...
$ch = curl_init('https://hamtagift.com/api/partner/v1/rates');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey, 'Accept: application/json'],
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($body === false) {
throw new RuntimeException('Hamta API unreachable: ' . $error);
}
$data = json_decode($body, true); // null for the plain-text 403/429 of the security layer
if ($status !== 200 || !is_array($data) || empty($data['ok'])) {
// 401: check the key. 429: wait for Retry-After. 503: keep your last good prices.
throw new RuntimeException('Hamta API error: ' . ($data['error'] ?? ('HTTP ' . $status)));
}
foreach ($data['rates'] as $rate) {
// Prices are decimal strings or null (= not configured). Keep them as strings
// (e.g. bcmath) rather than float for money.
$sellToCustomer = $rate['customerPrice']['retail']['buy'];
echo $rate['code'], ': ', $sellToCustomer ?? 'not configured', PHP_EOL;
}import os
from decimal import Decimal
import requests
API_KEY = os.environ["HAMTA_API_KEY"] # hamta_live_...
resp = requests.get(
"https://hamtagift.com/api/partner/v1/rates",
headers={"Authorization": f"Bearer {API_KEY}", "Accept": "application/json"},
timeout=10,
)
try:
data = resp.json()
except ValueError: # plain-text 403/429 from the security layer
data = None
if resp.status_code != 200 or not data or not data.get("ok"):
# 401: check the key. 429: wait for Retry-After. 503: keep your last good prices.
raise RuntimeError(f"Hamta API error: {(data or {}).get('error', resp.status_code)}")
for rate in data["rates"]:
price = rate["customerPrice"]["retail"]["buy"] # decimal string or None
print(rate["code"], Decimal(price) if price is not None else "not configured")// Node.js 18+, ES module (.mjs). Server side only.
const API_KEY = process.env.HAMTA_API_KEY; // hamta_live_...
const res = await fetch("https://hamtagift.com/api/partner/v1/rates", {
headers: { Authorization: `Bearer ${API_KEY}`, Accept: "application/json" },
signal: AbortSignal.timeout(10_000),
});
const data = await res.json().catch(() => null); // null for the plain-text 403/429
if (!res.ok || !data?.ok) {
// 401: check the key. 429: wait for Retry-After. 503: keep your last good prices.
throw new Error(`Hamta API error: ${data?.error ?? `HTTP ${res.status}`}`);
}
for (const rate of data.rates) {
// Decimal strings or null; parse with a decimal library, not Number, for money.
console.log(rate.code, rate.customerPrice.retail.buy ?? "not configured");
}# HAMTA_API_KEY holds your key (hamta_live_...)
curl -sS "https://hamtagift.com/api/partner/v1/rates" \
-H "Authorization: Bearer $HAMTA_API_KEY" \
-H "Accept: application/json"توصیهها
- نتیجه را روی سرور خود دستکم یک دقیقه کش کنید و برای هر بازدید صفحه درخواست جدید نفرستید.
- قیمتها را به صورت رشته یا نوع اعشاری دقیق (Decimal، bcmath) پردازش کنید، نه عدد اعشاری شناور (float).
- برای یافتن ابزار از فیلد code استفاده کنید؛ label فقط برای نمایش است.
- مقدار null را «تنظیم نشده» نمایش دهید و هرگز به جای آن عدد دیگری قرار ندهید.
- اگر درخواست ناموفق بود، آخرین نرخهای معتبر را همراه با زمان updatedAt آنها نگه دارید.
- برای هر سرویس یا محیط یک کلید جداگانه بسازید تا در صورت نیاز فقط همان را باطل کنید.
آماده اتصال هستید؟
کلید API را در پنل همکاران میسازید. اگر هنوز همکار همتا گیفت نیستید، برای ایجاد حساب همکاری با ما تماس بگیرید.