PaytechUZ API Documentation
Base URL: https://paytechuz-core.uz/api
Health Check
Ping
curl -X GET https://paytechuz-core.uz/api/ping/
Response (200):
{
"status": "ok"
}
Authentication
Send OTP
Send OTP to phone number. User retrieves code via Telegram bot.
curl -X POST https://paytechuz-core.uz/api/auth/send-otp/ \
-H "Content-Type: application/json" \
-d '{"phone": "+998901234567"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Yes | Phone number (+998XXXXXXXXX format) |
Response (200):
{
"message": "OTP created. Get your code via Telegram bot.",
"expires_in": 120
}
Error Response (400):
{
"phone": ["Invalid phone number format"]
}
Verify OTP
Verify OTP code and receive JWT tokens.
curl -X POST https://paytechuz-core.uz/api/auth/verify-otp/ \
-H "Content-Type: application/json" \
-d '{"phone": "+998901234567", "code": "123456"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| phone | string | Yes | Phone number |
| code | string | Yes | 6-digit OTP code |
Response (200):
{
"is_new_user": true,
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
Error Responses (400):
{"detail": "OTP not found"}
{"detail": "OTP has expired"}
{"detail": "Too many attempts"}
{"detail": "Invalid code. 2 attempts remaining"}
Get Profile
Get user profile details (requires authentication).
curl -X GET https://paytechuz-core.uz/api/auth/profile/ \
-H "Authorization: Bearer <access_token>"
Response (200):
{
"id": 1,
"phone": "+998901234567",
"first_name": "John",
"last_name": "Doe",
"created_at": "2024-01-15T10:30:00Z"
}
Update Profile
Update user profile (requires authentication).
curl -X PUT https://paytechuz-core.uz/api/auth/profile/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"first_name": "John", "last_name": "Doe"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| first_name | string | Yes | First name (max 150 chars) |
| last_name | string | No | Last name (max 150 chars) |
Response (200):
{
"message": "Profile updated successfully"
}
Projects
All project endpoints require authentication.
List Projects
curl -X GET https://paytechuz-core.uz/api/projects/ \
-H "Authorization: Bearer <access_token>"
Response (200):
[
{
"id": 1,
"name": "My Project",
"created_at": "2024-01-15T10:30:00Z",
"subscription": {
"tariff": "Basic",
"requests_limit": 1000,
"requests_used": 150,
"requests_remaining": 850,
"is_active": true,
"is_expired": false,
"expires_at": "2024-02-15T10:30:00Z"
}
},
{
"id": 2,
"name": "Another Project",
"created_at": "2024-01-16T14:20:00Z",
"subscription": null
}
]
Create Project
Creates a new project with default API key and free trial subscription.
curl -X POST https://paytechuz-core.uz/api/projects/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"name": "My New Project"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Project name (max 255 chars) |
Response (201):
{
"id": 1,
"name": "My New Project",
"api_key": "550e8400-e29b-41d4-a716-446655440000",
"tariff": "Free Trial",
"requests_limit": 100,
"expires_at": "2024-02-15T10:30:00Z",
"created_at": "2024-01-15T10:30:00Z"
}
Error Response (400):
{
"detail": "Project limit reached. Maximum 3 projects allowed."
}
Delete Project
curl -X DELETE https://paytechuz-core.uz/api/projects/1/ \
-H "Authorization: Bearer <access_token>"
Response (200):
{
"message": "Project deleted successfully"
}
Error Response (400):
{
"detail": "Project not found"
}
List API Keys
List all active API keys for a project.
curl -X GET https://paytechuz-core.uz/api/projects/1/api-keys/ \
-H "Authorization: Bearer <access_token>"
Response (200):
[
{
"id": 1,
"key": "550e8400-e29b-41d4-a716-446655440000",
"name": "default",
"created_at": "2024-01-15T10:30:00Z"
},
{
"id": 2,
"key": "660e8400-e29b-41d4-a716-446655440001",
"name": "production",
"created_at": "2024-01-16T14:20:00Z"
}
]
Create API Key
Generate a new API key for a project.
curl -X POST https://paytechuz-core.uz/api/projects/1/api-keys/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"name": "production"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | No | Key name (max 255 chars) |
Response (201):
{
"id": 2,
"key": "660e8400-e29b-41d4-a716-446655440001",
"name": "production",
"project_id": 1,
"created_at": "2024-01-16T14:20:00Z"
}
Revoke API Key
curl -X DELETE https://paytechuz-core.uz/api/api-keys/2/ \
-H "Authorization: Bearer <access_token>"
Response (200):
{
"message": "API key revoked successfully"
}
Error Response (400):
{
"detail": "API key not found"
}
Tariffs
List Tariffs
List all available tariffs (public endpoint).
curl -X GET https://paytechuz-core.uz/api/tariffs/
Response (200):
[
{
"id": 1,
"name": "Free Trial",
"slug": "free-trial",
"requests_limit": 100,
"price": "0.00",
"duration_days": 30
},
{
"id": 2,
"name": "Basic",
"slug": "basic",
"requests_limit": 1000,
"price": "9.99",
"duration_days": 30
},
{
"id": 3,
"name": "Pro",
"slug": "pro",
"requests_limit": 10000,
"price": "49.99",
"duration_days": 30
}
]
Subscribe to Tariff
Subscribe a project to a tariff (requires authentication).
- Free trial: Activates immediately
- Paid tariffs: Returns payment URL (Payme)
curl -X POST https://paytechuz-core.uz/api/tariffs/subscribe/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"project_id": 1, "tariff_slug": "basic", "return_url": "https://myapp.com/success"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| project_id | integer | Yes | Project ID |
| tariff_slug | string | Yes | Tariff slug |
| return_url | string | No | URL to redirect after payment |
Response (201) - Free Trial (immediate activation):
{
"id": 1,
"tariff": "Free Trial",
"requests_limit": 100,
"requests_used": 0,
"requests_remaining": 100,
"expires_at": "2024-02-15T10:30:00Z"
}
Response (201) - Paid Tariff (requires payment):
{
"requires_payment": true,
"invoice_id": 1,
"payment_url": "https://checkout.paycom.uz/base64encodedstring",
"amount": "9.99",
"tariff": "Basic"
}
Error Responses (400):
{"detail": "Project not found"}
{"detail": "Tariff not found"}
Get Subscription Status
Get current subscription status for a project (requires authentication).
curl -X GET https://paytechuz-core.uz/api/tariffs/projects/1/status/ \
-H "Authorization: Bearer <access_token>"
Response (200) - Active subscription:
{
"has_subscription": true,
"tariff": "Basic",
"requests_limit": 1000,
"requests_used": 150,
"requests_remaining": 850,
"is_expired": false,
"expires_at": "2024-02-15T10:30:00Z"
}
Response (200) - No subscription:
{
"has_subscription": false,
"message": "No active subscription"
}
Check API Key
Check API key status and remaining requests (public endpoint).
curl -X POST https://paytechuz-core.uz/api/tariffs/check-api-key/ \
-H "Content-Type: application/json" \
-d '{"api_key": "550e8400-e29b-41d4-a716-446655440000"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| api_key | uuid | Yes | API key UUID |
Response (200) - Valid:
{
"valid": true,
"project_id": 1,
"project_name": "My Project",
"tariff": "Basic",
"requests_remaining": 850,
"expires_at": "2024-02-15T10:30:00Z"
}
Response (200) - Invalid:
{
"valid": false,
"error": "No active subscription for this project"
}
{
"valid": false,
"error": "Subscription has expired"
}
{
"valid": false,
"error": "Request limit exceeded"
}
Error Response (400):
{
"detail": "Invalid or inactive API key"
}
Use Request
Consume one request from API key's quota (public endpoint).
curl -X POST https://paytechuz-core.uz/api/tariffs/use-request/ \
-H "Content-Type: application/json" \
-d '{"api_key": "550e8400-e29b-41d4-a716-446655440000"}'
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
| api_key | uuid | Yes | API key UUID |
Response (200) - Success:
{
"success": true,
"requests_used": 151,
"requests_remaining": 849,
"requests_limit": 1000
}
Response (200) - Failure:
{
"success": false,
"error": "Invalid or inactive API key"
}
{
"success": false,
"error": "No active subscription"
}
{
"success": false,
"error": "Subscription expired"
}
{
"success": false,
"error": "Request limit exceeded"
}
Error Responses
Authentication Errors
401 Unauthorized:
{
"detail": "Authentication credentials were not provided."
}
{
"detail": "Given token not valid for any token type",
"code": "token_not_valid",
"messages": [
{
"token_class": "AccessToken",
"token_type": "access",
"message": "Token is invalid or expired"
}
]
}
Validation Errors
400 Bad Request:
{
"field_name": ["Error message"]
}
Rate Limiting
429 Too Many Requests:
{
"detail": "Request was throttled. Expected available in X seconds."
}
Payment
Get Payment Status
Check the status of a payment/invoice (requires authentication).
curl -X GET https://paytechuz-core.uz/api/payment/status/1/ \
-H "Authorization: Bearer <access_token>"
Response (200) - Found:
{
"found": true,
"invoice_id": 1,
"project_id": 7,
"project_name": "My Project",
"tariff": "Basic",
"amount": "9.99",
"status": "pending",
"provider": "payme",
"payment_url": "https://checkout.paycom.uz/base64encodedstring",
"created_at": "2024-01-15T10:30:00Z"
}
Invoice Status Values:
| Status | Description |
|---|---|
| pending | Payment not yet completed |
| paid | Payment successful, subscription activated |
| cancelled | Payment was cancelled |
| expired | Payment expired |
Response (200) - Not Found:
{
"found": false,
"error": "Invoice not found"
}
Payment Flow
- User calls
POST /api/tariffs/subscribe/withreturn_url - For paid tariffs, API returns
payment_urlandinvoice_id - User is redirected to Payme checkout
- After payment, user is redirected to
return_url?invoice_id=123 - Frontend extracts
invoice_idfrom URL query params - Frontend calls
GET /api/payment/status/{invoice_id}/to verify payment - If
statusispaid, subscription is active