API

Що таке API. Клієнт-серверна архітектура

Визначення програмного інтерфейсу (API), аналогії з реального світу, клієнт-серверна модель, типи API та їх роль у сучасній розробці.

Що таке API. Клієнт-серверна архітектура

Цей матеріал — не «сухий» переказ визначень. Це менторська сесія, де кожне нове поняття вводиться через проблему, яку воно вирішує. Ми не просто дамо визначення API — ми покажемо, навіщо воно з'явилось і чому без нього сучасна розробка неможлива.

1. Проблема: Чому програми не можуть просто «поговорити»?

Уявіть ситуацію: ви розробляєте мобільний застосунок для замовлення кави. Користувач натискає кнопку «Замовити лунго», і... що відбувається далі?

Десь на сервері є база даних із рецептами, кавовими машинами, цінами, поточними замовленнями. Ваш мобільний застосунок не має прямого доступу до цієї бази — і це правильно. Якби кожен телефон мав прямий доступ до серверної бази даних, це було б:

  • Небезпечно — будь-хто міг би змінити ціни або видалити замовлення інших людей.
  • Крихко — зміна структури бази зламала б усі клієнтські додатки одночасно.
  • Неможливо масштабувати — мільйони прямих підключень до однієї бази покладуть сервер за лічені секунди.

Потрібен посередник — чітко визначений контракт, який каже: «Ось що ти можеш запитати, ось у якому форматі, і ось що ти отримаєш у відповідь». Цей контракт називається API.

Що ви дізнаєтесь?

  • Що таке API і чому це не просто «набір URL-адрес»
  • Клієнт-серверна модель та її фундаментальні принципи
  • Типи API за аудиторією: внутрішнє, партнерське, публічне
  • Чому HTTP API є вибором за замовчуванням для публічних сервісів

Пререквізити

  • Базове розуміння протоколу HTTP (запити, відповіді, статус-коди)
  • Основи мови C# та ASP.NET Core Minimal API

2. Визначення: Що таке API?

API (Application Programming Interface, програмний інтерфейс застосунку) — це контракт між двома програмними компонентами, який визначає:

  1. Які операції доступні (наприклад, «створити замовлення», «отримати список рецептів»).
  2. Який формат мають запити та відповіді (параметри, типи даних, структура).
  3. Які гарантії надає сервер (що станеться при помилці, як довго кешувати відповідь).
Аналогія з реального світу: API — це як меню у ресторані. Ви не заходите на кухню і не кажете кухарю, які інгредієнти змішати. Замість цього ви дивитеся в меню (API-документацію), обираєте страву (операцію), вказуєте побажання (параметри запиту), і офіціант (HTTP) несе ваше замовлення на кухню (сервер). Ви не знаєте, як влаштована кухня, і вам не потрібно це знати — достатньо того, що меню чітко описує, що можна замовити.

Важливо розуміти: API — це не реалізація, а специфікація. Меню ресторану не змінюється від того, чи працює на кухні шеф-кухар або стажер. Так само, API визначає контракт взаємодії, а не те, як саме сервер виконує запит всередині.

Чому API — це не просто «набір URL-адрес»?

Поширена помилка — ототожнювати API з переліком ендпоінтів (URL-адрес). Але API — поняття значно ширше:

АспектПросто URL-адресиПовноцінний API
Формат данихНе визначенийJSON, XML, Protobuf — чітко задані
Обробка помилокДовільнаСтандартизовані коди та формати
ВерсіонуванняВідсутнєПродумана стратегія сумісності
ДокументаціяНемаєOpenAPI/Swagger специфікація
ГарантіїЖоднихSLA, ліміти, політика кешування
БезпекаНе продуманаАутентифікація, авторизація, rate limiting

Саме тому дизайн API — це окрема інженерна дисципліна, якій присвячено цей модуль.


3. Клієнт-серверна архітектура

Базова модель

Клієнт-серверна архітектура — це фундаментальний паттерн побудови розподілених систем, де компоненти поділяються на дві ролі:

  • Клієнт — ініціатор запиту. Це може бути мобільний застосунок, браузер, інший сервер або навіть IoT-пристрій.
  • Сервер — обробник запиту. Він зберігає дані, виконує бізнес-логіку та повертає відповідь.
Loading diagram...
sequenceDiagram
    participant C as 📱 Клієнт<br/>(мобільний додаток)
    participant S as 🖥️ Сервер<br/>(ASP.NET Core API)
    participant DB as 🗄️ База даних

    C->>S: POST /v1/orders<br/>{"recipe": "lungo", "volume": "300ml"}
    S->>DB: INSERT INTO orders...
    DB-->>S: OK, id = 42
    S-->>C: 201 Created<br/>{"id": 42, "status": "processing"}

    Note over C,S: Клієнт не знає, як влаштований сервер.<br/>Сервер не знає, хто саме є клієнтом.

Ключовий принцип цієї моделі: клієнт і сервер не знають внутрішнього устрою один одного. Клієнт не знає, чи сервер написаний на C#, Python чи Go. Сервер не знає, чи клієнт — це браузер, мобільний додаток чи скрипт у терміналі. Вони спілкуються виключно через контракт API.

Чому це важливо?

Ця незалежність має величезні практичні наслідки:

🔄 Незалежна еволюція

Ви можете повністю переписати бекенд з Python на C# — якщо контракт API залишається тим самим, жоден клієнт не зламається.

📱 Мультиплатформність

Один API обслуговує мобільний додаток, веб-сайт, десктопний клієнт, інтеграцію з партнерами — усіх одночасно.

⚡ Масштабування

Між клієнтом і сервером можна додати проксі, балансувальники навантаження, кеші — без зміни коду обох сторін.

🧪 Тестування

Клієнт можна тестувати з мок-сервером. Сервер можна тестувати без клієнта, надсилаючи HTTP-запити вручну.

4. Типи API за аудиторією

Не всі API однакові. Залежно від того, хто є споживачем API, змінюються вимоги до його дизайну, документації та безпеки.

Внутрішнє API (Internal / Private API)

Використовується тільки всередині організації — для взаємодії між мікросервісами, внутрішніми інструментами, бекенд-компонентами.

Program.cs
// Внутрішній API для сервісу повідомлень
// Доступний лише в приватній мережі
var app = WebApplication.Create(args);

app.MapPost("/internal/notifications/send", 
    (NotificationRequest req) =>
{
    // Немає зовнішньої автентифікації —
    // довіряємо мережевому контуру
    return Results.Ok(new { sent = true });
});

app.Run();

Характеристики:

  • Менше уваги документації — розробники обох сторін сидять в одному офісі
  • Можна використовувати бінарні протоколи (gRPC) для максимальної продуктивності
  • Оновлення без довгого циклу deprecation — контролюєте обидва боки

Партнерське API (Partner API)

Надається обмеженому колу зовнішніх компаній-партнерів за договором.

Program.cs
// Партнерське API для B2B інтеграції
var app = WebApplication.Create(args);

app.MapGet("/v1/partners/{partnerId}/orders", 
    (string partnerId, HttpContext ctx) =>
{
    // Перевірка API-ключа партнера
    var apiKey = ctx.Request.Headers["X-Partner-ApiKey"]
        .FirstOrDefault();

    if (string.IsNullOrEmpty(apiKey))
        return Results.Unauthorized();

    // Повернення замовлень лише цього партнера
    return Results.Ok(new { 
        partner_id = partnerId,
        orders = new[] { 
            new { id = 1, status = "completed" } 
        }
    });
});

app.Run();

Характеристики:

  • Обов'язкова аутентифікація (API-ключі, OAuth)
  • Детальна документація та підтримка
  • Версіонування з довгим циклом deprecation

Публічне API (Public / Open API)

Доступне будь-якому розробнику в Інтернеті. Це те, з чим ви найчастіше будете працювати.

Program.cs
// Публічне API для мобільного додатку
var app = WebApplication.Create(args);

app.MapGet("/v1/recipes", () =>
{
    // Будь-хто може отримати список рецептів
    return Results.Ok(new[] 
    {
        new { id = "lungo", title = "Лунго", volume = "250ml" },
        new { id = "americano", title = "Американо", volume = "350ml" }
    });
});

app.MapPost("/v1/orders", (OrderRequest order) =>
{
    // Створення замовлення вимагає авторизації
    return Results.Created($"/v1/orders/{42}", new { id = 42 });
});

app.Run();

record OrderRequest(string Recipe, string CoffeeMachineId);

Характеристики:

  • Максимально детальна документація (OpenAPI/Swagger)
  • Суворе версіонування та зворотна сумісність
  • Rate limiting, автентифікація, захист від зловживань
  • JSON-over-HTTP — вибір за замовчуванням, оскільки ця технологія зрозуміла максимально широкому колу програмістів і дозволяє розробляти клієнтські додатки практично на будь-якій платформі
З книги Константинова: Для публічних API надання JSON-over-HTTP ендпоінтів є вибором за замовчуванням. Практика надання публічних API у форматі gRPC поступово набирає популярності, але поки ще незначна на загальному фоні. Проблема вибору технології виникає лише для непублічних API загального призначення.

5. Від бібліотечного API до мережевого API

Термін «API» з'явився задовго до вебу. Спочатку він означав інтерфейс бібліотеки — набір функцій, які можна викликати з коду:

// Бібліотечне API — виклик функції напряму
var result = Math.Sqrt(144); // 12

З розвитком Інтернету та розподілених систем виникла потреба викликати функції на іншому комп'ютері, через мережу. Так з'явилися мережеві API (Network API або Web API).

Loading diagram...
graph LR
    subgraph "Бібліотечне API"
        A["Код програми"] -->|"Math.Sqrt(144)"| B["Бібліотека Math"]
    end
    
    subgraph "Мережеве API"
        C["Клієнт"] -->|"GET /api/sqrt?n=144"| D["Сервер"]
    end

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style C fill:#f59e0b,stroke:#b45309,color:#ffffff
    style D fill:#f59e0b,stroke:#b45309,color:#ffffff

Принципова різниця:

АспектБібліотечне APIМережеве API
ВикликПрямий (в межах процесу)Через мережу (HTTP, gRPC)
ШвидкістьНаносекундиМілісекунди (мережева затримка)
НадійністьГарантована (якщо код працює)Мережа може впасти в будь-який момент
Формат данихНативні типи мовиСеріалізація (JSON, Protobuf)
ВерсіонуванняЧерез NuGet/npm версіїЧерез URL або заголовки
Критична різниця: мережеві виклики завжди ненадійні. Мережа може обірватися посеред запиту, сервер може відповісти таймаутом, проксі може змінити відповідь. Це фундаментально впливає на дизайн API — саме тому існують концепції ідемпотентності, retry-політик та токенів ідемпотентності, які ми детально розберемо у наступних статтях.

6. Навіщо вивчати дизайн API?

Може здатися: «Навіщо окремий модуль для API? Достатньо написати кілька ендпоінтів і все працює». Але ось сценарій із реального життя:

Понеділок: «Все просто»

Ви створюєте один ендпоінт: GET /orders — повертає список замовлень. Все працює.

Вівторок: «А як фільтрувати?»

Фронтенд-розробник просить додати фільтр за статусом: GET /orders?status=active. Додаєте — працює.

Середа: «А як шукати по кількох рецептах?»

Потрібно шукати замовлення для лунго і латте одночасно. GET /orders?recipe=lungo&recipe=latte? Але стандарту передачі масивів у URL не існує. Доводиться вигадувати: recipe=lungo,latte? Чи recipe[]=lungo&recipe[]=latte? Кожен фреймворк обробляє це по-різному.

Четвер: «Дані не оновлюються!»

Клієнт кешував GET /orders, і тепер показує застарілі дані. Потрібна політика кешування: Cache-Control, ETag, If-None-Match.

П'ятниця: «Замовлення створюється двічі!»

Мережа обірвалась під час POST /orders. Клієнт повторив запит — і створив дублікат замовлення. Потрібен токен ідемпотентності.

Кожна з цих проблем має відомі та перевірені рішення. Саме їх ми й вивчатимемо в цьому модулі.


7. Що нас чекає: Структура модуля

Цей модуль побудований за принципом «від простого до складного». Кожна наступна тема спирається на попередню:

Loading diagram...
graph TD
    A["01. Що таке API"] --> B["02. Формати даних"]
    B --> C["03. Парадигми та REST"]
    C --> D["04. HTTP-методи та статус-коди"]
    D --> E["05. Організація за REST"]
    E --> F["06. URL та CRUD"]
    F --> G["07. Іменування та стандарти"]
    G --> H["08. Валідація та ліміти"]
    H --> I["09. Помилки в HTTP API"]
    I --> J["10. Ідемпотентність"]
    J --> K["11. Пагінація"]
    K --> L["12. Безпека та кешування"]
    L --> M["13. Процес проєктування"]

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style M fill:#f59e0b,stroke:#b45309,color:#ffffff

Протягом усього модуля ми будемо використовувати один наскрізний приклад — API сервісу замовлення кави. Цей приклад дозволяє продемонструвати всі паттерни: від простого CRUD до складних сценаріїв синхронізації та обробки помилок.


8. Практичні завдання

Рівень 1: Базовий

Рівень 2: Аналітичний

Рівень 3: Проєктування


9. Резюме

API — це контракт

Не реалізація, не набір URL-адрес — а формальна угода між клієнтом і сервером про формат, операції та гарантії взаємодії.

Клієнт ≠ Сервер

Фундаментальний принцип: обидві сторони незалежні, не знають внутрішнього устрою одна одної, спілкуються виключно через контракт.

Тип визначає дизайн

Внутрішнє, партнерське та публічне API мають кардинально різні вимоги до документації, безпеки та зворотної сумісності.

Дизайн API — інженерна дисципліна

Кожна «проста» задача («додай фільтр», «поверни список») швидко перетворюється на складну інженерну проблему без системного підходу.

Далі: у наступній статті ми розберемо формати даних — JSON, XML, TOML та бінарні формати. Навчимося обирати правильний формат і розберемо стратегії стиснення для оптимізації трафіку.

Copyright © 2026