برنامه نویسی

ای پی آی (API) چیست

ای پی آی قراردادی است که دو برنامه از طریق آن با هم حرف می زنند: یکی درخواستی با شکل مشخص می فرستد و دیگری پاسخی با شکل مشخص برمی گرداند، بدون اینکه هیچ کدام لازم باشد بداند آن یکی داخلش چطور کار می کند. تقریبا هر چیزی که در وب دکمه اش را می زنید و داده ای از جای دیگر می آورد، پشتش یک API است.

  • درس ۱۱ از ۱۴
  • مقدماتی
  • رایگان، بدون ثبت نام

قرارداد بین دو برنامه، تخته به تخته

برنامه شما

لازم نیست بداند طرف مقابل داخلش چطور کار می کند

آدرس اندپوینتروش: GET یا POSTپارامترهاپاسخ: کد وضعیت و بدنه

سرویس مقابل

فقط چیزی را می دهد که قرارداد گفته، و به اندازه ای که سهمیه اجازه بدهد

پل را طرف مقابل ساخته و او هم می تواند عوضش کند. برای همین شماره نسخه در آدرس API هست: تا وقتی نسخه یک زنده است، شکل پاسخ همان می ماند.

آخرین بررسی: فکت ها و نام ابزارهای این درس در همین تاریخ با منابعشان بازبینی شده اند.

یک مثال که همین صفحه می تواند نشانتان بدهد

ابزار رایگان بررسی سرعت سایت همین سایت را باز کنید و یک آدرس بدهید. چیزی که پشت آن دکمه اتفاق می افتد، دقیقا تعریف API است و سه طرف دارد.

مرورگر شما آدرس را به سرور ما می فرستد، سرور ما همان آدرس را به سرویس PageSpeed گوگل می دهد، گوگل یک متن ساختاریافته با فرمت JSON برمی گرداند که پر از عدد است، و سرور ما از آن چند عدد را برمی دارد و به صفحه می دهد. هیچ آدمی وسط این زنجیره نیست و هیچ کدام از این سه برنامه هم نمی داند آن یکی داخلش چطور نوشته شده.

ای پی آی همین قرارداد است: مجموعه ای از آدرس ها که هر کدام ورودی مشخصی می گیرند و خروجی مشخصی می دهند. اسمش مخفف رابط برنامه نویسی کاربردی است و همان کلمه رابط، مهم ترین بخشش است. مثل پریز برق: شکل پریز قرارداد است و شما لازم نیست بدانید برق از کجا می آید.

و یک نکته که برای یادگیری کوتاه ترین راه است: بیشتر API های وب امروز چیز عجیبی نیستند، فقط یک آدرس اینترنتی اند که به جای صفحه HTML، متن JSON برمی گردانند. اگر بلدید یک لینک را در مرورگر باز کنید، اولین تماس API را هم می توانید بزنید.

هر تماس چهار تکه دارد

تکه اول آدرس است، که به هر کدامش یک اندپوینت می گویند و کار مشخصی انجام می دهد. تکه دوم روش است: GET یعنی چیزی می خواهم و POST یعنی چیزی می فرستم که باید ثبت شود. تکه سوم پارامترها است، همان ورودی ها، و تکه چهارم پاسخ.

پاسخ خودش دو بخش دارد و تازه کارها معمولا فقط یکی را می بینند. بخش اول کد وضعیت است: ۲۰۰ یعنی انجام شد، ۴۰۰ یعنی درخواست شما ایراد داشت، ۴۰۴ یعنی چنین چیزی نیست، ۴۲۹ یعنی زیادی سریع درخواست دادید و ۵۰۰ یعنی سمت آنها چیزی خراب شد. بخش دوم بدنه است، معمولا JSON.

خواندن همین کد وضعیت است که وقت شما را نجات می دهد. ۴ در ابتدای کد یعنی ایراد از سمت درخواست دهنده است و باید درخواست را درست کنید؛ ۵ یعنی ایراد از سمت سرویس است و درست کردن درخواست فایده ای ندارد. کسی که این تفکیک را بلد نیست، ساعت ها کد خودش را می گردد در حالی که سرویس مقابل خراب بوده.

API خود این سایت هم همین شکل است. شش اندپوینت زیر نام فضای rgb/v1 داریم: چهار تای اول با GET بررسی دامنه و سئو و سرعت و امنیت را انجام می دهند و دو تای بعدی با POST فرم تماس و شمارش بازدید را. هر پاسخ هم یک پوشش ثابت دارد: یک کلید که می گوید موفق بود یا نه، به علاوه یا داده یا پیام خطا. این یکنواختی برای مصرف کننده API از هر مستنداتی مهم تر است.

کلید و محدودیت نرخ: چرا هیچ API رایگان بی نهایتی وجود ندارد

هر تماس API برای طرف مقابل هزینه دارد و به همین دلیل دو ابزار برای کنترلش وجود دارد. اول کلید: رشته ای که هویت شما را مشخص می کند تا معلوم باشد این درخواست ها مال کیست. دوم محدودیت نرخ: سقفی روی تعداد درخواست در یک بازه زمانی، که وقتی رد شود پاسخ ۴۲۹ می گیرید.

یک اتفاق واقعی روی همین سایت نشان می دهد چرا این دو مهم اند. ابزار سرعت ما مدتی بدون کلید با API گوگل کار می کرد و درست هم جواب می داد. بعد بدون هیچ تغییری از سمت ما، همان درخواست ها شروع کردند به گرفتن ۴۲۹ و در متن خطا سهمیه روزانه صفر بود. راه حل یک خط بود: گرفتن کلید و گذاشتنش در تنظیمات سایت. درسی که ماند این است: رفتار امروز یک API قرارداد فردا نیست، مخصوصا وقتی از سرویسی بدون کلید استفاده می کنید.

سمت دیگرش هم آموزنده است: API خود ما هم محدودیت دارد، چون عمومی است و هیچ کلیدی نمی خواهد. سقف ها به ازای هر بازدیدکننده و در بازه پنج دقیقه اند: بررسی دامنه ۲۰ بار، سئو ۱۰ بار، امنیت ۱۰ بار و سرعت ۶ بار، چون هر بررسی سرعت خودش یک تماس گران با سرویس بیرونی است. فرم تماس حساب جدا دارد و ۵ ارسال در ساعت.

اگر روزی خودتان API عمومی نوشتید، این را از تجربه بنویسید نه از توصیه: محدودیت نرخ را از روز اول بگذارید، حتی اگر بی مصرف به نظر برسد. اضافه کردنش بعد از اینکه یک اسکریپت شروع به کوبیدن سرویس شما کرد، همیشه دیر است.

سقف درخواست ابزارهای این سایت، در پنج دقیقه

  1. بررسی دامنه ۲۰ بار ارزان ترین بررسی، پس بازترین سقف
  2. بررسی سئو ۱۰ بار صفحه هدف را کامل دانلود می کند
  3. بررسی امنیت ۱۰ بار همان جنس هزینه را دارد
  4. بررسی سرعت ۶ بار هر بار یک تماس گران با سرویس بیرونی

هر سقف به ازای هر بازدیدکننده است و از کد همین سایت خوانده شده. فرم تماس در این نمودار نیست چون واحدش فرق دارد: پنج ارسال در ساعت.

وقتی ورودی را کاربر می نویسد: محافظی که همه فراموشش می کنند

ابزارهای این سایت یک ویژگی مشترک دارند که آنها را از یک API معمولی جدا می کند: آدرسی که بررسی می شود را بازدیدکننده می نویسد، و بعد سرور ما به آن آدرس درخواست می زند. یعنی یک غریبه می تواند به سرور ما بگوید به کجا وصل شود.

اگر جلوی این کار گرفته نشود، کسی می تواند به جای سایت خودش، یک آدرس داخلی شبکه بنویسد. آن وقت سرور ما، که داخل شبکه است و به جاهایی دسترسی دارد که مرورگر یک غریبه ندارد، آن آدرس را باز می کند و نتیجه را هم به او نشان می دهد. اسم این دسته آسیب پذیری SSRF است و درمانش هم مشخص و شناخته شده است.

محافظی که در کد این سایت نوشته ایم چهار کار می کند و ترتیبش هم مهم است. فقط http و https را می پذیرد؛ فقط پورت ۸۰ و ۴۴۳ را قبول می کند؛ آدرسی که نام کاربری و رمز داخلش باشد را رد می کند؛ و مهم تر از همه، نام دامنه را به آی پی تبدیل می کند و همه آی پی های برگشتی را بررسی می کند، و اگر حتی یکی از آنها خصوصی یا رزرو شده باشد کل درخواست رد می شود.

همان بند آخر است که معمولا فراموش می شود. بستن آدرس هایی که مستقیم آی پی خصوصی دارند کار ساده ای است و همه انجامش می دهند؛ ولی کسی که بخواهد از این محافظ رد شود، یک دامنه معمولی می سازد که به آی پی داخلی اشاره می کند. تنها راه گرفتن جلوی این، همان قدم تبدیل نام به آی پی و بررسی نتیجه است، نه نگاه کردن به شکل آدرس.

چهار بررسی قبل از اینکه سرور به آدرس کاربر وصل شود

  • فقط http و https

    هر طرح دیگری رد می شود، چون فقط این دو برای این کار لازم اند.

  • فقط پورت ۸۰ و ۴۴۳

    پورت غیر استاندارد معمولا یعنی کسی سراغ سرویس دیگری روی همان میزبان است.

  • بدون نام کاربری و رمز در آدرس

    آدرسی که اعتبارنامه در خودش دارد، یا اشتباه است یا تله.

  • تبدیل نام به آی پی و بررسی همه نتیجه ها

    مهم ترین قدم و همانی که فراموش می شود: یک دامنه معمولی می تواند به آی پی داخلی اشاره کند.

این ترتیب برای API ای است که ورودی آدرس از کاربر می گیرد. اگر API شما چنین ورودی ندارد، این محافظ لازم نیست و جایش چیزهای دیگری لازم است.

API ای که مال شما نیست، روزی جواب نمی دهد

وقتی برنامه شما به سرویس دیگری وصل می شود، یک وابستگی ساخته اید که کنترلش دست شما نیست. سرویس ممکن است کند شود، قطع شود، شکل پاسخ را عوض کند یا سهمیه رایگانش را بردارد. هیچ کدام از اینها اتفاق نادری نیست و برنامه ای که فقط حالت موفق را در نظر گرفته، همان روز از کار می افتد.

سه دفاع ساده تقریبا همیشه کافی است. اول مهلت زمانی: هر تماس بیرونی باید سقف انتظار داشته باشد، وگرنه کندی آنها به کندی شما تبدیل می شود. دوم کش: پاسخ را برای مدت کوتاهی نگه دارید تا برای یک ورودی تکراری دوباره تماس نگیرید. سوم نقشه دوم: وقتی جواب نیامد، برنامه باید بداند چه بگوید.

ابزار سرعت همین سایت هر سه را دارد و مثال زنده ای است: نتیجه هر آدرس را ده دقیقه نگه می دارد، پس اگر همان آدرس دوباره بررسی شود تماسی به گوگل زده نمی شود؛ و اگر پاسخی از آن سرویس نیاید، به جای نشان دادن خطا یک بررسی محلی و ساده تر اجرا می شود تا کاربر دست خالی نماند.

و نکته ای که فقط بعد از یکی دو بار سوختن یاد گرفته می شود: نسخه بندی. آن v1 در نام فضای API خود ما یعنی اگر روزی شکل پاسخ عوض شود، نسخه دو ساخته می شود و کسی که به نسخه یک وصل است نمی شکند. برای API عمومی این احترام به مصرف کننده است و هزینه اش هم فقط سه حرف بیشتر در آدرس است.

مسیر سریع با هوش مصنوعی

کاری که با هوش مصنوعی واقعا کوتاه می شود، خواندن مستندات یک API ناآشنا و رسیدن به اولین تماس درست است؛ همان کاری که قبلا نیم روز طول می کشید. ولی نسخه ای که جواب می دهد یک تفاوت با «برایم کد بنویس» دارد: به جای کد، اول یک تماس آزمایشی می خواهید که بتوانید خودتان اجرا کنید و ببینید. کد نوشتن بعد از دیدن پاسخ واقعی، کار ده دقیقه است؛ کد نوشتن قبل از آن، حدس زدن است.

  1. نشانی صفحه مستندات آن API را بردارید و متن همان صفحه را بفرستید، نه فقط لینکش. اگر مدل صفحه را نبیند، از حافظه اش جواب می دهد و مستندات API ها زود عوض می شوند.
  2. با دستور زیر یک تماس آزمایشی بخواهید که بدون کلید یا با یک کلید تستی قابل اجرا باشد، و آن را خودتان اجرا کنید. اولین چیزی که می بینید کد وضعیت است و همان می گوید در چه مرحله ای هستید.
  3. پاسخ واقعی را که گرفتید، همان را برگردانید و بگویید فقط این سه فیلد را لازم دارم. حالا مدل شکل واقعی داده را می بیند و کدی که می نویسد با آنچه واقعا برمی گردد جور است.
  4. در آخر بخواهید حالت های خطا را هم اضافه کند: مهلت زمانی، کد ۴۲۹ و پاسخی که اصلا JSON نیست. این سه حالت همان هایی اند که در روز اول هیچ وقت پیش نمی آیند و در ماه دوم حتما.

نسخه آماده کپی

متن مستندات این API را در ادامه می گذارم:

{متن صفحه مستندات}

می خواهم این کار را انجام بدهم: {مثلا وضعیت یک سفارش را با شماره اش بگیرم}

به همین ترتیب جواب بده:
۱. یک تماس آزمایشی بده که بتوانم همین حالا در ترمینال اجرا کنم، با روش و آدرس و پارامترهای درست. اگر کلید لازم است، بگو از کجا گرفته می شود و در کدام قسمت درخواست قرار می گیرد.
۲. بگو در پاسخ موفق دنبال کدام فیلدها باید بگردم.
۳. فهرست کن این اندپوینت چه کدهای وضعیتی برمی گرداند و هر کدام یعنی چه.
۴. بگو محدودیت نرخ یا سهمیه اش چقدر است. اگر در مستندات نوشته نشده، بنویس که نوشته نشده و حدس نزن.

هنوز هیچ کدی برای برنامه ننویس؛ فقط تماس آزمایشی.

قبل از اعتماد به خروجی: دو چیز را قبل از اجرای هر تماسی که مدل داده خودتان بررسی کنید. اول اینکه آن تماس چه کاری می کند: یک <code>GET</code> معمولا فقط می خواند، ولی <code>POST</code> و <code>DELETE</code> ممکن است چیزی را در حساب واقعی شما عوض کنند و برگرداندنش با شما نیست. دوم اینکه کلید API یک رمز است: در دستوری که در چت می نویسید کلید واقعی نگذارید، و اگر یک بار گذاشتید همان را باطل کنید و کلید تازه بسازید. و یک مورد که هر بار پیش می آید: اگر مستندات چیزی درباره سقف درخواست نگفته باشد، مدل معمولا یک عدد معقول می سازد. آن عدد از هیچ جا نیامده.

هوش مصنوعی در این کار

برای این موضوع مدل زبانی دو کار را خوب انجام می دهد و یک کار را اصلا نباید بکند. خوب: خواندن مستندات طولانی و بیرون کشیدن همان چند خط لازم، و ساختن کدی که یک پاسخ JSON را به شکل قابل استفاده دربیاورد. نباید: ساختن مستندات از حافظه. اگر صفحه مستندات را ندهید، مدل نام فیلدها و پارامترها را با اطمینان کامل می سازد و شما ساعتی را صرف اشکال زدایی کدی می کنید که هیچ وقت نمی توانست کار کند.

ابزارهایی که واقعا کمک می کنند

  • Claude برای دستور همین صفحه مناسب است، چون متن بلند مستندات را می شود کامل چسباند و بعد پاسخ واقعی API را هم در همان گفتگو داد. ایران در هیچ کدام از دو فهرست کشورهای پشتیبانی شده انتروپیک نیست؛ این را از صفحه خود انتروپیک خوانده ایم.
  • Claude Code وقتی به جای یک تماس، دارید یک ادغام کامل می نویسید مفیدتر است، چون کد پروژه را می بیند و می تواند همان تماس آزمایشی را هم اجرا کند. رایگان نصب می شود ولی بدون اشتراک کلود یا حساب کنسول انتروپیک کار نمی کند.
  • Gemini برای تبدیل یک پاسخ JSON به کد و برای کارهای مکانیکی تکراری، یک مدل سریع و ارزان کافی است. صفحه خود گوگل می گوید اپ وب جمنای در بیش از دویست و سی کشور و منطقه کار می کند و ایران در آن فهرست نیست.

کجا نتیجه معکوس می دهد

خطر مشخص این موضوع، اندپوینت و پارامتری است که وجود ندارد. مدل شکل API های رایج را خوب می شناسد و برای همین وقتی مستندات را ندیده باشد، چیزی می سازد که شبیه یک API واقعی است: نام فیلدها منطقی اند، ساختار درست به نظر می رسد، و هیچ کدامشان در سرویس شما وجود ندارند. انتروپیک خودش این دسته اطمینان بی پشتوانه را در مستنداتش توهم می نامد و روش های کم کردنش را توضیح می دهد؛ ساده ترینش برای این کار همان دادن متن مستندات است.
خطر دوم مال کلید است. کلید API رمز عبور برنامه شماست و کسی که آن را داشته باشد می تواند به حساب شما درخواست بزند و سهمیه شما را خرج کند. پس کلید واقعی نه در چت می رود، نه در کد داخل مخزن؛ جایش فایل تنظیمات بیرون از مخزن است، همان چیزی که در درس گیت گفتیم. برای اینکه بدانید هر ابزار از ایران چطور قابل پرداخت است راهنمای خرید را ببینید.

منبع ها: MDN: an overview of HTTP MDN: HTTP response status codes Anthropic: reduce hallucinations Anthropic: supported countries Google: where the Gemini web app is available

حد این توصیه

این درس درباره API های وب است، همان هایی که با HTTP کار می کنند و JSON برمی گردانند، چون امروز بیشتر چیزی که با آن سر و کار دارید همین است. چند چیز عمدا بیرون مانده: احراز هویت جدی تر مثل OAuth که وقتی برنامه شما به حساب کاربر در سرویس دیگری وصل می شود لازم است، وبهوک که در آن جهت برعکس است و سرویس مقابل به شما زنگ می زند، و سبک هایی مثل GraphQL که قرارداد دیگری دارند. و یک مرز که همین جا هم صادق است: کد وضعیت ۲۰۰ فقط می گوید تماس برقرار شد و پاسخی آمد. اینکه محتوای آن پاسخ درست باشد، ضمانت جداگانه ای می خواهد که هیچ API ای نمی دهد.

از تجربه خود ما

همه چیزهایی که در این درس درباره API خود این سایت گفته شد، از یک فایل در قالب همین سایت خوانده شده و قابل دیدن است: شش اندپوینت زیر نام فضای rgb/v1، چهار تا با GET و دو تا با POST، هیچ کدام کلید نمی خواهند و همه شان محدودیت نرخ به ازای هر بازدیدکننده دارند. دو چیز در آن کد هست که در آموزش ها کمتر دیده می شود. اول محافظ SSRF که فقط به ظاهر آدرس نگاه نمی کند: نام دامنه را به آی پی تبدیل می کند و اگر هر کدام از آی پی های برگشتی خصوصی یا رزرو شده باشد کل درخواست را رد می کند. دوم رفتار ابزار سرعت وقتی سرویس بیرونی جواب نمی دهد: به جای نشان دادن خطا، یک بررسی محلی ساده تر اجرا می شود و نتیجه هر آدرس هم ده دقیقه نگه داشته می شود تا تماس تکراری زده نشود. ماجرای کلید هم واقعی است: همان تماس مدتی بدون کلید کار می کرد و بعد با سهمیه روزانه صفر شروع کرد به گرفتن ۴۲۹، و با اضافه کردن یک کلید در تنظیمات سایت درست شد.

سوال هایی که واقعا پرسیده می شوند

فرق API و وب سرویس چیست؟

وب سرویس یک API است که از طریق شبکه در دسترس است. هر API لازم نیست از شبکه رد شود؛ کتابخانه ای که در همان برنامه صدا می زنید هم API خودش را دارد. در گفتگوی روزمره اما این دو را معمولا به یک معنا به کار می برند.

برای اولین تماس API از کجا شروع کنم؟

از یک API عمومی که کلید نمی خواهد و با GET کار می کند؛ آدرسش را در مرورگر باز کنید و JSON را ببینید. وقتی شکل پاسخ برایتان آشنا شد، همان تماس را با ابزاری مثل curl و بعد از داخل کد بزنید. این ترتیب چند ساعت سردرگمی را حذف می کند.

کد ۴۲۹ گرفتم، یعنی چه؟

یعنی از سقف تعداد درخواست رد شده اید و باید صبر کنید، نه اینکه کدتان ایراد دارد. اول ببینید سرویس در پاسخ گفته چقدر صبر کنید؛ بعد اگر تماس ها تکراری اند، پاسخ را کش کنید تا تعدادشان کم شود.