مستندات API
نسخهی ۱ — این مستندات بهتدریج و همراه با افزودهشدن قابلیتهای جدید کامل میشود.
با این API میتوانید بدون ورود به پنل، شمارههای اقتصادی خود را مدیریت کنید و ماندهی اعتبار را بخوانید. ارسال صورتحساب و گزارشها در نسخههای بعدی اضافه میشود (بخش «بهزودی»).
آدرس پایه
https://api.tpinta.com/v1
- همهی درخواستها فقط روی HTTPS پذیرفته میشوند.
- بدنهی درخواست و پاسخ
JSONبا کدگذاری UTF-8 است؛ در درخواستهای دارای بدنه، هدرContent-Type: application/jsonبفرستید. - نام فیلدها camelCase است. زمانها بهصورت UTC و در قالب ISO 8601 برگردانده میشوند.
شروع سریع
- وارد پنل شوید و از منوی «کلید API» یک کلید بسازید (برای ساخت، رمز پنل لازم است). کلید فقط یک بار نمایش داده میشود؛ آن را جای امن ذخیره کنید.
- با موبایل، رمز پنل و کلید API یک توکن بگیرید.
- توکن را در هدر
Authorization: Bearer ...همهی درخواستهای بعدی بفرستید.
# ۱) دریافت توکن
curl -X POST https://api.tpinta.com/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"mobile":"09120000000","password":"رمز-پنل","apiKey":"ei_..."}'
# ۲) استفاده از توکن
curl https://api.tpinta.com/v1/credit/balance \
-H "Authorization: Bearer ACCESS_TOKEN"
const base = 'https://api.tpinta.com/v1';
const r = await fetch(base + '/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ mobile: '09120000000', password: 'رمز-پنل', apiKey: 'ei_...' })
});
const { data } = await r.json();
const bal = await fetch(base + '/credit/balance', {
headers: { Authorization: 'Bearer ' + data.accessToken }
});
console.log(await bal.json());
using System.Net.Http.Json;
using System.Net.Http.Headers;
var http = new HttpClient { BaseAddress = new Uri("https://api.tpinta.com/v1/") };
var res = await http.PostAsJsonAsync("auth/token",
new { mobile = "09120000000", password = "رمز-پنل", apiKey = "ei_..." });
var doc = await res.Content.ReadFromJsonAsync<System.Text.Json.JsonElement>();
var token = doc.GetProperty("data").GetProperty("accessToken").GetString();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
Console.WriteLine(await http.GetStringAsync("credit/balance"));
import requests
base = "https://api.tpinta.com/v1"
r = requests.post(base + "/auth/token", json={
"mobile": "09120000000", "password": "رمز-پنل", "apiKey": "ei_..."})
token = r.json()["data"]["accessToken"]
b = requests.get(base + "/credit/balance", headers={"Authorization": "Bearer " + token})
print(b.json())
احراز هویت
هویت شما با سه مورد تأیید میشود: موبایل پنل، رمز پنل و کلید API. این سه فقط برای دریافت توکن لازماند؛ بعد از آن فقط توکن میفرستید.
| مورد | توضیح |
|---|---|
| کلید API | با پیشوند ei_ و ۴۶ نویسه. از پنل ساخته میشود؛ حداکثر ۵ کلید فعال برای هر حساب. با ابطال کلید در پنل، توکنهای آن حداکثر ظرف حدود ۳۰ ثانیه از کار میافتند. |
| توکن (Bearer) | پیشفرض ۶۰ دقیقه اعتبار دارد (مقدار دقیق در فیلد expiresIn بر حسب ثانیه میآید). پس از انقضا یا خطای 401 دوباره توکن بگیرید. |
| تغییر رمز پنل | همهی توکنهای قبلی را باطل میکند. |
429 too_many_attempts). این مسدودسازی ورود به پنل را تحت تأثیر قرار نمیدهد.قالب پاسخها
همهی پاسخها (موفق یا ناموفق) یک قالب ثابت دارند.
موفق
{ "success": true, "data": { ... } }
ناموفق
{
"success": false,
"error": { "code": "validation_failed", "message": "نام مؤدی / شرکت را وارد کنید.", "field": "name" },
"traceId": "00-4bf92f35..."
}
error.codeرا در برنامهی خود بررسی کنید (ثابت است)؛messageفارسی و برای نمایش به انسان است و ممکن است تغییر کند.fieldفقط برای خطاهای اعتبارسنجی میآید و نام فیلدِ بدنهی درخواست است.- هنگام گزارش مشکل به پشتیبانی، مقدار
traceIdرا همراه بفرستید.
کدهای خطا
| HTTP | code | معنی |
|---|---|---|
| 400 | invalid_request | بدنهی درخواست یا قالب آن درست نیست (JSON خراب، Content-Type نادرست و…) |
| 400 | validation_failed | مقدار یک فیلد نامعتبر است؛ فیلد در field آمده |
| 401 | invalid_credentials | موبایل، رمز یا کلید API اشتباه است (عمداً مشخص نمیکنیم کدام) |
| 401 | unauthorized | توکن ارسال نشده، نامعتبر یا منقضی است |
| 403 | forbidden | دسترسی به این منبع مجاز نیست |
| 404 | not_found | مسیر یا منبع پیدا نشد |
| 409 | conflict | تداخل با دادهی موجود (مثلاً شماره اقتصادی تکراری) |
| 422 | rule_violation | درخواست از نظر قالب درست است اما قانون کسبوکار اجازه نمیدهد |
| 429 | too_many_attempts | تلاش ناموفق ورود بیش از حد؛ هدر Retry-After را ببینید |
| 429 | rate_limited | تعداد درخواست بیش از سقف مجاز |
| 500 | server_error | خطای داخلی؛ با traceId به پشتیبانی اطلاع دهید |
| 503 | service_unavailable | سرویس موقتاً در دسترس نیست؛ کمی بعد دوباره تلاش کنید |
محدودیت نرخ (Rate Limit)
| محدوده | سقف پیشفرض |
|---|---|
| دریافت توکن | ۲۰ درخواست در ۱۰ دقیقه برای هر IP |
| درخواستهای خواندنی | ۱۲۰ درخواست در دقیقه برای هر توکن |
| درخواستهای نوشتنی (ثبت و ویرایش) | ۳۰ درخواست در ۱۰ دقیقه برای هر توکن |
| کل درخواستها | ۶۰۰ درخواست در دقیقه برای هر IP |
با عبور از سقف، پاسخ 429 با کد rate_limited میگیرید. سقفها ممکن است در آینده تغییر کنند؛ برنامهی شما باید با 429 کمی صبر کند و دوباره تلاش کند.
دریافت توکن
بدنه حداکثر ۴ کیلوبایت.
| فیلد | نوع | الزامی | توضیح |
|---|---|---|---|
mobile | string | بله | موبایل ثبتشده در پنل (مثل 09120000000) |
password | string | بله | رمز پنل |
apiKey | string | بله | کلید API ساختهشده در پنل (ei_...) |
نمونه درخواست
POST /v1/auth/token HTTP/1.1
Host: api.tpinta.com
Content-Type: application/json
{
"mobile": "09120000000",
"password": "رمز-پنل",
"apiKey": "ei_..."
}
نمونه پاسخ موفق — 200
{
"success": true,
"data": {
"accessToken": "CfDJ8...",
"tokenType": "Bearer",
"expiresIn": 3600
}
}
نمونه پاسخهای خطا
اطلاعات اشتباه:
HTTP/1.1 401
{
"success": false,
"error": { "code": "invalid_credentials", "message": "اطلاعات ورود یا کلید API نامعتبر است." },
"traceId": "00-4bf92f35..."
}
قالب نادرست موبایل، رمز یا کلید:
HTTP/1.1 400
{
"success": false,
"error": { "code": "invalid_request", "message": "موبایل، رمز یا کلید API در قالب درست نیست." },
"traceId": "00-4bf92f35..."
}
تلاش ناموفق زیاد (هدر Retry-After بر حسب ثانیه میآید):
HTTP/1.1 429
Retry-After: 600
{
"success": false,
"error": { "code": "too_many_attempts", "message": "تلاش ناموفق بیش از حد مجاز بوده است؛ بعداً دوباره تلاش کنید." },
"traceId": "00-4bf92f35..."
}
اطلاعات حساب
برای آزمایش اتصال و اطمینان از سالمبودن توکن. بدنه ندارد.
نمونه درخواست
GET /v1/me HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
نمونه پاسخ موفق — 200
{ "success": true, "data": { "displayName": "شرکت نمونه", "mobile": "09120000000" } }
نمونه پاسخ خطا — توکن نامعتبر یا منقضی
HTTP/1.1 401
{
"success": false,
"error": { "code": "unauthorized", "message": "توکن دسترسی نامعتبر یا منقضی است. دوباره از /v1/auth/token توکن بگیرید." },
"traceId": "00-4bf92f35..."
}
فهرست شمارههای اقتصادی
همهی شمارههای اقتصادی حساب شما را برمیگرداند. بدنه و پارامتر ندارد.
نمونه درخواست
GET /v1/economic-ids HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
نمونه پاسخ موفق — 200
{
"success": true,
"data": {
"items": [
{
"id": 12,
"code": "10101234567",
"type": 1,
"name": "شرکت نمونه",
"branch": null,
"nationalId": "10101234567",
"memoryId": "A1B2C3",
"isTest": true,
"signingMode": 1,
"active": true,
"createdAt": "2026-10-20T08:15:00Z",
"hasPrivateKey": true,
"hasCertificate": true,
"hasInvoices": false
}
]
}
}
کلید خصوصی و گواهی هرگز برگردانده نمیشوند؛ فقط وجود آنها با hasPrivateKey و hasCertificate مشخص است. hasInvoices نشان میدهد با این شماره صورتحسابی ثبت شده است (در این حالت تغییر کد و محیط ممکن نیست).
اگر هنوز شمارهای ثبت نکرده باشید: { "success": true, "data": { "items": [] } }
نمونه پاسخ خطا — توکن نامعتبر یا منقضی
HTTP/1.1 401
{
"success": false,
"error": { "code": "unauthorized", "message": "توکن دسترسی نامعتبر یا منقضی است. دوباره از /v1/auth/token توکن بگیرید." },
"traceId": "00-4bf92f35..."
}
ثبت شماره اقتصادی
محدودیت حجم بدنه: حدود ۶۰ کیلوبایت.
| فیلد | نوع | الزامی | توضیح |
|---|---|---|---|
type | number | بله | نوع مؤدی: 1 حقوقی · 2 حقیقی · 3 مشارکت مدنی · 4 اتباع غیرایرانی |
name | string | بله | نام مؤدی / شرکت؛ ۲ تا ۲۰۰ نویسه؛ نویسههای < و > مجاز نیست |
code | string | بله | شماره اقتصادی؛ فقط رقم. طول: ۱۱ رقم برای حقوقی و مشارکت مدنی، ۱۴ رقم برای حقیقی و اتباع |
nationalId | string | بله | فقط رقم. حقوقی: شناسه ملی ۱۱ رقم · حقیقی: کد ملی ۱۰ رقم · مشارکت مدنی: شناسه مشارکت ۱۱ رقم · اتباع: کد فراگیر ۱۲ رقم |
memoryId | string | بله | شناسه یکتای حافظه مالیاتی؛ ۶ نویسهی حروف بزرگ انگلیسی یا عدد |
branch | string | خیر | نام شعبه؛ حداکثر ۱۰۰ نویسه |
isTest | boolean | خیر | true آزمایشی (sandbox) · false عملیاتی. پیشفرض: true |
signingMode | number | خیر | 1 امضا با گواهی · 2 بدون گواهی (فقط کلید خصوصی). پیشفرض: 1 |
privateKey | string | بله* | کلید خصوصی RSA حداقل ۲۰۴۸ بیت، بدون رمز، قالب PEM یا Base64 |
certificate | string | بله* | گواهی امضا (PEM یا Base64) که با کلید خصوصی تطبیق داشته باشد؛ در حالت signingMode = 2 لازم نیست |
active | boolean | خیر | پیشفرض: true |
* کلید خصوصی و گواهی با هم بررسی میشوند: کلید باید با گواهی جفت باشد، گواهی در محیط عملیاتی نباید منقضی باشد و تاریخ شروع آن نباید در آینده باشد.
نمونه درخواست
POST /v1/economic-ids HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"type": 1,
"name": "شرکت نمونه",
"code": "10101234567",
"nationalId": "10101234567",
"memoryId": "A1B2C3",
"isTest": true,
"privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
"certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}
نمونه پاسخ موفق — 201
{ "success": true, "data": { "id": 12 } }
نمونه پاسخهای خطا
فیلد نامعتبر (اینجا طول شماره اقتصادی):
HTTP/1.1 400
{
"success": false,
"error": { "code": "validation_failed", "message": "شماره اقتصادی شخص حقوقی باید دقیقاً ۱۱ رقم باشد.", "field": "code" },
"traceId": "00-4bf92f35..."
}
شماره تکراری در همان محیط (آزمایشی/عملیاتی):
HTTP/1.1 409
{
"success": false,
"error": { "code": "conflict", "message": "این شماره اقتصادی در همین محیط قبلاً ثبت شده است." },
"traceId": "00-4bf92f35..."
}
توکن نامعتبر:
HTTP/1.1 401
{
"success": false,
"error": { "code": "unauthorized", "message": "توکن دسترسی نامعتبر یا منقضی است. دوباره از /v1/auth/token توکن بگیرید." },
"traceId": "00-4bf92f35..."
}
کد 422 rule_violation هم برای قوانینی که دیتابیس اعمال میکند ممکن است؛ متن دقیق آن در message میآید.
ویرایش شماره اقتصادی
ویرایش جزئی است: فقط فیلدهایی را بفرستید که میخواهید تغییر کنند؛ فیلدهای ارسالنشده بدون تغییر میمانند. فیلدها همان فیلدهای ثبتاند.
- برای پاککردن نام شعبه
"branch": ""بفرستید. - برای تغییر کلید یا گواهی، هر دو را با هم بفرستید (تا تطبیق آنها بررسی شود).
- اگر با این شماره صورتحساب ثبت شده باشد، تغییر
codeو محیط (isTest) رد میشود (422). - برای فعال/غیرفعالکردن از مسیر جداگانهی زیر استفاده کنید. حذف شماره اقتصادی از طریق API ممکن نیست و فقط از پنل انجام میشود.
نمونه درخواست
PUT /v1/economic-ids/12 HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{ "name": "شرکت نمونه (نام جدید)", "branch": "شعبه مرکزی" }
نمونه پاسخ موفق — 200
{ "success": true, "data": { "id": 12 } }
نمونه پاسخهای خطا
شمارهای با این id در حساب شما نیست:
HTTP/1.1 404
{
"success": false,
"error": { "code": "not_found", "message": "شماره اقتصادی یافت نشد." },
"traceId": "00-4bf92f35..."
}
فیلد نامعتبر:
HTTP/1.1 400
{
"success": false,
"error": { "code": "validation_failed", "message": "نام مؤدی حداکثر ۲۰۰ نویسه میتواند باشد.", "field": "name" },
"traceId": "00-4bf92f35..."
}
توکن نامعتبر: همان پاسخ 401 unauthorized بخش قبل. تغییر code یا isTest وقتی صورتحساب ثبت شده باشد، 422 rule_violation میدهد و متن آن در message است.
فعال / غیرفعالکردن
نمونه درخواست
PUT /v1/economic-ids/12/active HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{ "active": false }
نمونه پاسخ موفق — 200
{ "success": true, "data": { "id": 12, "active": false } }
نمونه پاسخهای خطا
فیلد active ارسال نشده:
HTTP/1.1 400
{
"success": false,
"error": { "code": "validation_failed", "message": "فیلد active (true یا false) الزامی است.", "field": "active" },
"traceId": "00-4bf92f35..."
}
شماره متعلق به حساب شما نیست یا وجود ندارد:
HTTP/1.1 404
{
"success": false,
"error": { "code": "not_found", "message": "شماره اقتصادی یافت نشد." },
"traceId": "00-4bf92f35..."
}
مانده اعتبار
فقطخواندنی؛ شارژ حساب از طریق پنل انجام میشود. بدنه ندارد.
نمونه درخواست
GET /v1/credit/balance HTTP/1.1
Host: api.tpinta.com
Authorization: Bearer ACCESS_TOKEN
نمونه پاسخ موفق — 200
{
"success": true,
"data": {
"balance": 1500000,
"invoiceFee": 3000,
"remainingInvoices": 500
}
}
| فیلد | توضیح |
|---|---|
balance | ماندهی اعتبار، با همان واحدی که در پنل نمایش داده میشود |
invoiceFee | هزینهی هر صورتحساب |
remainingInvoices | تعداد صورتحساب قابل ارسال با ماندهی فعلی؛ در صورت نبود هزینهی تعریفشده null است |
اعداد بالا فقط نمونهاند.
نمونه پاسخ خطا — توکن نامعتبر یا منقضی
HTTP/1.1 401
{
"success": false,
"error": { "code": "unauthorized", "message": "توکن دسترسی نامعتبر یا منقضی است. دوباره از /v1/auth/token توکن بگیرید." },
"traceId": "00-4bf92f35..."
}
در صورت عبور از سقف نرخ:
HTTP/1.1 429
{
"success": false,
"error": { "code": "rate_limited", "message": "تعداد درخواستها بیش از حد مجاز است؛ کمی بعد دوباره تلاش کنید." },
"traceId": "00-4bf92f35..."
}
فازهای بعدی بهزودی
- گزارش صورتحسابهای ارسالی و گزارش خطاها
- ارسال صورتحساب (تکی)، همراه با شناسهی یکتای درخواست برای جلوگیری از ارسال تکراری
- استعلام وضعیت صورتحساب (تکی)
- ارسال و استعلام گروهی
هر قابلیت پس از آمادهشدن به همین صفحه اضافه میشود.