Реалізація продажу API-доступу (за ключем/підпискою) на сайті

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

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація продажу API-доступу (за ключем/підпискою) на сайті
Складна
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація продажу API-доступу (за ключем/підпискою) на веб-сайті

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

Структура API-ключів та тарифів

CREATE TABLE api_plans (
    id           SERIAL PRIMARY KEY,
    name         TEXT,
    requests_per_month  INTEGER,   -- -1 = unlimited
    requests_per_minute INTEGER,
    endpoints    JSONB,            -- ['GET /v1/products', 'GET /v1/orders']
    price_monthly NUMERIC(10,2),
);

CREATE TABLE api_keys (
    id              BIGSERIAL PRIMARY KEY,
    user_id         BIGINT REFERENCES users(id),
    plan_id         INTEGER REFERENCES api_plans(id),
    key_hash        TEXT UNIQUE,   -- bcrypt хеш ключа
    key_prefix      CHAR(8),       -- перші 8 символів для відображення
    status          TEXT,          -- active, revoked, expired
    expires_at      TIMESTAMPTZ,
    created_at      TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE api_usage (
    id          BIGSERIAL PRIMARY KEY,
    api_key_id  BIGINT,
    endpoint    TEXT,
    method      TEXT,
    status_code SMALLINT,
    response_ms INTEGER,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

Генерація та зберігання ключів

class ApiKeyService
{
    public function generate(int $userId, int $planId): array
    {
        $rawKey = 'sk_' . Str::random(48);  // Приклад: sk_A1B2C3D4...

        ApiKey::create([
            'user_id'    => $userId,
            'plan_id'    => $planId,
            'key_hash'   => Hash::make($rawKey),
            'key_prefix' => substr($rawKey, 0, 8),
            'status'     => 'active',
        ]);

        // Ключ показується користувачу ОДИН РАЗ — далі лише хеш
        return ['key' => $rawKey, 'prefix' => substr($rawKey, 0, 8)];
    }
}

Middleware аутентифікації API

class ApiKeyAuthMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        $rawKey = $request->header('X-API-Key')
            ?? $request->bearerToken()
            ?? $request->query('api_key');

        if (!$rawKey) {
            return response()->json(['error' => 'API key required'], 401);
        }

        // Швидкий пошук за префіксом, потім перевірка хеша
        $prefix = substr($rawKey, 0, 8);
        $apiKey = ApiKey::where('key_prefix', $prefix)->where('status', 'active')->first();

        if (!$apiKey || !Hash::check($rawKey, $apiKey->key_hash)) {
            return response()->json(['error' => 'Invalid API key'], 401);
        }

        $request->setApiKey($apiKey);
        return $next($request);
    }
}

Rate Limiting

class ApiRateLimiter
{
    public function check(ApiKey $apiKey): RateLimitResult
    {
        $plan = $apiKey->plan;

        // Ліміт за хвилину через Redis sliding window
        $minuteKey   = "rate:{$apiKey->id}:minute:" . floor(time() / 60);
        $minuteCount = Redis::incr($minuteKey);
        Redis::expire($minuteKey, 120);

        if ($minuteCount > $plan->requests_per_minute) {
            return RateLimitResult::exceeded(
                limit: $plan->requests_per_minute,
                reset: (floor(time() / 60) + 1) * 60
            );
        }

        // Місячний ліміт
        $monthKey   = "rate:{$apiKey->id}:month:" . date('Y-m');
        $monthCount = Redis::incr($monthKey);
        Redis::expireat($monthKey, strtotime('first day of next month'));

        if ($plan->requests_per_month !== -1 && $monthCount > $plan->requests_per_month) {
            return RateLimitResult::quotaExceeded($plan->requests_per_month);
        }

        return RateLimitResult::ok(
            remaining: $plan->requests_per_month === -1
                ? null
                : $plan->requests_per_month - $monthCount
        );
    }
}

Інформаційна панель використання API

function ApiUsageDashboard({ apiKeyId }: Props) {
  const { data } = useQuery({
    queryKey: ['api-usage', apiKeyId],
    queryFn: () => fetchUsageStats(apiKeyId),
  });

  return (
    <div className="grid grid-cols-3 gap-6">
      <StatCard label="Запитів сьогодні"  value={data?.today} />
      <StatCard label="Запитів у місяць"  value={data?.month} limit={data?.monthLimit} />
      <StatCard label="Середній час відповіді (мс)" value={data?.avgResponseMs} />
    </div>
  );
}

Графік

API-монетизація з ключами, тарифами та rate limiting: 8–12 робочих днів.