Click FRP Tool API
Official developer documentation

Two integration modes.
One protected gateway.

Connect legacy tools through the Native Compatibility API or build new server-side integrations with Secure B2B V1. Both modes use the same protected billing, provider selection and recovery engine.

POST /login/api/api_sell.php POST /login/api/v1/sell.php FRP + FDL Protected billing
Integration profiles

Choose the correct API

Use one mode per client. Do not mix authentication fields from both profiles.

Advanced server integration

Secure B2B API V1

For new server-side integrations using a one-time issued Bearer credential and an explicit idempotency key.

  • JSON only
  • Bearer authentication
  • IP allowlist support
  • Explicit safe retries
Legacy tools

Native Compatibility API

Use the customer's own panel username and password. Telegram, database and upstream-provider credentials are never used here.

POSThttps://clickfrptool.com/login/api/api_sell.php

Authentication

Native fields
username: CUSTOMER_PANEL_USERNAME
password: CUSTOMER_PANEL_PASSWORD
Content-Type: application/json

Account requirements

  • Active panel account
  • API Access enabled by administrator
  • Active B2B client assignment
  • Permission and credit for requested service
Compatibility response: HTTP 200 is preserved. Always evaluate the JSON boolean success; never treat HTTP 200 alone as a completed operation.
New integrations

Secure B2B API V1

Keep this credential on a protected server. Do not embed it in distributable desktop applications.

POSThttps://clickfrptool.com/login/api/v1/sell.php
Required headers
Authorization: Bearer cft_live_PUBLIC_ID.SECRET
Idempotency-Key: UNIQUE_KEY_16_TO_80_CHARACTERS
Content-Type: application/json
Accept: application/json
Safe retry: resend the identical JSON with the same Idempotency-Key after a lost response or recovery_pending. Never create another key for that same device operation.
Service data

Build the correct configblob

FRP and FDL use Base64, but their source data is intentionally different.

FRP source

Create the complete device JSON first, then Base64-encode that entire JSON.

Before Base64
{
  "productName": "XIAOMI GLOBAL",
  "deviceName": "REAL_DEVICE_CODENAME",
  "token": "TOKEN_READ_FROM_DEVICE"
}

FDL source

Base64-encode only the raw Fastboot token. Do not place the FDL token inside JSON before encoding.

Before Base64
RAW_FASTBOOT_TOKEN_READ_FROM_DEVICE

Native FRP request

JSON
{
  "username": "CUSTOMER_USERNAME",
  "password": "CUSTOMER_PASSWORD",
  "soc": "frp",
  "configblob": "BASE64_OF_COMPLETE_FRP_JSON"
}

Native FDL request

JSON
{
  "username": "CUSTOMER_USERNAME",
  "password": "CUSTOMER_PASSWORD",
  "soc": "fdl",
  "configblob": "BASE64_OF_RAW_FASTBOOT_TOKEN"
}
Implementations

Integration examples

The first two examples use Native Compatibility. The C# and Python examples demonstrate Secure B2B V1.

Native · cURL
curl --request POST "https://clickfrptool.com/login/api/api_sell.php" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{"username":"CUSTOMER_USERNAME","password":"CUSTOMER_PASSWORD","soc":"frp","configblob":"BASE64_OF_COMPLETE_FRP_JSON"}'
Native · PHP cURL
<?php

$endpoint = 'https://clickfrptool.com/login/api/api_sell.php';
$deviceJson = json_encode([
    'productName' => 'XIAOMI GLOBAL',
    'deviceName' => $realDeviceCodename,
    'token' => $tokenReadFromDevice,
], JSON_UNESCAPED_SLASHES);
$payload = json_encode([
    'username' => $customerUsername,
    'password' => $customerPassword,
    'soc' => 'frp',
    'configblob' => base64_encode($deviceJson),
], JSON_UNESCAPED_SLASHES);

$curl = curl_init($endpoint);
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 15,
    CURLOPT_TIMEOUT => 150,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS => $payload,
]);

$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
$result = json_decode((string) $response, true);
if (!is_array($result) || empty($result['success']) || empty($result['data']['response'])) {
    throw new RuntimeException($result['message'] ?? 'API request failed');
}
$authorization = (string) $result['data']['response'];
C# · HttpClient
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

public static async Task<string> RequestFdlAsync(
    string credential, string rawFastbootToken, string operationKey)
{
    using (var client = new HttpClient { Timeout = TimeSpan.FromSeconds(150) })
    using (var request = new HttpRequestMessage(HttpMethod.Post,
        "https://clickfrptool.com/login/api/v1/sell.php"))
    {
        request.Headers.Authorization =
            new AuthenticationHeaderValue("Bearer", credential);
        request.Headers.Add("Idempotency-Key", operationKey);
        request.Headers.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        string configblob = Convert.ToBase64String(
            Encoding.UTF8.GetBytes(rawFastbootToken));
        string json = "{\"service\":\"fdl\",\"configblob\":\"" +
            configblob + "\"}";
        request.Content = new StringContent(json, Encoding.UTF8, "application/json");

        using (HttpResponseMessage response = await client.SendAsync(request))
            return await response.Content.ReadAsStringAsync();
    }
}
Python · requests
import base64
import os
import uuid
import requests

endpoint = "https://clickfrptool.com/login/api/v1/sell.php"
credential = os.environ["CLICK_FRP_API_CREDENTIAL"]
operation_key = str(uuid.uuid4())
configblob = base64.b64encode(raw_fastboot_token.encode()).decode()

response = requests.post(
    endpoint,
    headers={
        "Authorization": f"Bearer {credential}",
        "Idempotency-Key": operation_key,
        "Accept": "application/json",
    },
    json={"service": "fdl", "configblob": configblob},
    timeout=(15, 150),
)
result = response.json()
Timeout: use a client read timeout of at least 150 seconds. Native Compatibility automatically derives duplicate protection from the customer and device payload. V1 clients must preserve their original body and Idempotency-Key for retries.
JSON schema

Responses

Both modes use success and return authorization only in data.response.

Native success

HTTP 200
{
  "status": 200,
  "success": true,
  "message": "Authorization generated successfully",
  "request_id": "32_HEX_CHARACTERS",
  "data": {
    "response": "AUTHORIZATION_TOKEN",
    "credit": "394.00",
    "amount_charged": "1.00",
    "service": "fdl",
    "reused": false
  }
}

Native error

HTTP 200 compatibility
{
  "status": 200,
  "success": false,
  "message": "Not enough credit",
  "request_id": "32_HEX_CHARACTERS",
  "error_code": "insufficient_credit"
}
Parser configuration: response path data.response, success path success, expected value true.
Client workflow

From device to authorization

The API generates authorization; the client tool remains responsible for device communication.

01

Read device data

Obtain the real model/codename and device token using the tool's established Fastboot protocol.

02

Request authorization

Build the correct Base64 payload, send one POST operation and require success: true.

03

Write and reboot

Pass only data.response to the tool's existing write routine. Reboot with fastboot reboot only after confirmed write success.

Do not guess a write command: Xiaomi authorization commands vary by protocol. Never substitute an arbitrary fastboot flash or fastboot oem instruction.
Failure handling

Error matrix

Native mode uses top-level error_code; V1 uses error.code. Messages are for people, not program logic.

HTTPError codeMeaningRequired action
400invalid_idempotency_keyOperation key is missing or malformed.Create a valid 16–80 character key before the first attempt.
401invalid_api_keyCredential is invalid, incomplete or rotated.Stop and request a credential rotation.
402insufficient_creditThe account balance is lower than the service price.Add credit and retry with the same operation data.
403account_disabledThe API client or user account is disabled.Contact the account administrator.
403ip_not_allowedThe request source is outside the configured allowlist.Add the correct fixed public IP.
403service_not_allowedFRP or FDL is not enabled for this client.Request service permission.
409request_in_progressThe same operation is currently processing.Wait briefly, then resend identical JSON with the same key.
409idempotency_conflictThe key was reused with different data.Do not retry until the integration bug is corrected.
422invalid_configblobThe Base64 payload does not match the service contract.Correct the payload before retrying.
422provider_rejectedThe provider rejected the operation.No Click credit was charged. Verify device data.
429rate_limit_exceededThe client exceeded its per-minute request limit.Wait for the Retry-After value.
502upstream_unavailableThe provider failed before returning valid authorization.No Click credit was charged. Retry according to support guidance.
503recovery_pendingAuthorization is protected and settlement is pending.Retry identical JSON with the same key.
503provider_status_unknownThe upstream result is ambiguous.Do not create another operation. Contact support with request_id.
503maintenanceThe B2B gateway is temporarily disabled.Wait and retry later.
Production rules

Security practices

Integrations are safest when secrets stay server-side and operational data is deliberately minimized.

A

Protect credentials

Store credentials in an environment variable or protected server configuration. Rotate immediately after suspected exposure.

B

Redact logs

Never log the Authorization header, configblob, raw device token or returned authorization response.

C

Validate every response

Check both the HTTP status and JSON success value. Keep the request ID for safe support investigation.