Name | limitly-python JSON |
Version |
1.0.3
JSON |
| download |
home_page | None |
Summary | Official Python SDK for Limitly - API Key management, plans, users and request validation |
upload_time | 2025-08-04 09:51:30 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | MIT |
keywords |
limitly
api
rate-limiting
api-keys
sdk
python
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# limitly-python
Official Python SDK for [Limitly](https://www.limitly.dev) - API Key management, plans, users and request validation.
## 🚀 Installation
```bash
pip install limitly-python
```
```bash
poetry add limitly-python
```
```bash
pipenv install limitly-python
```
## 📖 Basic Usage
### Initialization
```python
from limitly import Limitly
limitly = Limitly(api_key="your_limitly_api_key")
```
### Request Validation
The most common use case is validating your users' requests:
```python
# Validate a request
result = await limitly.validation.validate(
"user_api_key",
"/api/users",
"GET"
)
if result.success:
print("Request allowed")
print(f"Current usage: {result.details.current_usage}")
print(f"Limit: {result.details.limit}")
else:
print(f"Request denied: {result.error}")
```
### API Key Management
```python
# List all API Keys
keys = await limitly.api_keys.list()
print(f"API Keys: {keys.data}")
# Create a new API Key
new_key = await limitly.api_keys.create(
name="New API Key",
user_id=123
)
print(f"New API Key: {new_key.data.api_key}")
# Get usage for an API Key
usage = await limitly.api_keys.get_usage("key-id")
print(f"Usage: {usage.data}")
```
### Plan Management
```python
# Create a plan
plan = await limitly.plans.create(
name="Basic Plan",
description="Plan for basic users",
max_requests=10000,
request_period="month"
)
# Get plan usage statistics
plan_usage = await limitly.plans.get_usage(plan.data.id)
print(f"Plan usage: {plan_usage.data}")
```
### User Management
```python
# Create a user
user = await limitly.users.create(
name="John Doe",
email="john@example.com",
plan_id="plan-id"
)
# Get user usage
user_usage = await limitly.users.get_usage(user.data.user_id)
print(f"User usage: {user_usage.data}")
```
## 🔧 Configuration
### Configuration Options
```python
from limitly import Limitly
limitly = Limitly(
api_key="your_limitly_api_key",
base_url="https://your-project.supabase.co/functions/v1", # optional
timeout=30 # optional, default: 30 seconds
)
```
### Request Options
You can pass additional options to any method:
```python
result = await limitly.api_keys.list(
timeout=10,
headers={"X-Custom-Header": "value"}
)
```
## 📚 Complete API
### Request Validation
#### `validation.validate(api_key, endpoint, method, options=None)`
Validates a user request.
```python
result = await limitly.validation.validate(
"user_api_key",
"/api/users",
"GET"
)
```
#### `validation.validate_request(data, options=None)`
Validates a request with data object.
```python
result = await limitly.validation.validate_request({
"api_key": "user_api_key",
"endpoint": "/api/users",
"method": "GET"
})
```
### API Keys
#### `api_keys.list(options=None)`
Lists all API Keys.
#### `api_keys.create(data, options=None)`
Creates a new API Key.
```python
key = await limitly.api_keys.create({
"name": "New API Key",
"user_id": 123, # optional
"plan_id": "plan-id", # optional
"status": "active" # optional
})
```
#### `api_keys.get(key_id, options=None)`
Gets a specific API Key.
#### `api_keys.update(key_id, data, options=None)`
Updates an API Key.
#### `api_keys.delete(key_id, options=None)`
Deletes an API Key (soft delete).
#### `api_keys.regenerate(key_id, options=None)`
Regenerates an API Key.
#### `api_keys.get_usage(key_id, options=None)`
Gets usage statistics for an API Key.
#### `api_keys.get_requests(key_id, options=None)`
Gets request history for an API Key.
### Plans
#### `plans.list(options=None)`
Lists all plans.
#### `plans.create(data, options=None)`
Creates a new plan.
```python
plan = await limitly.plans.create({
"name": "Basic Plan",
"description": "Plan for basic users",
"max_requests": 10000,
"request_period": "month", # 'day', 'week', 'month', 'year'
"is_active": True
})
```
#### `plans.get(plan_id, options=None)`
Gets a specific plan.
#### `plans.update(plan_id, data, options=None)`
Updates a plan.
#### `plans.delete(plan_id, options=None)`
Deletes a plan.
#### `plans.get_usage(plan_id, options=None)`
Gets usage statistics for a plan.
#### `plans.get_users(plan_id, options=None)`
Gets all users assigned to a plan.
#### `plans.get_keys(plan_id, options=None)`
Gets all API Keys assigned to a plan.
### Users
#### `users.list(options=None)`
Lists all users.
#### `users.create(data, options=None)`
Creates a new user.
```python
user = await limitly.users.create({
"name": "John Doe",
"email": "john@example.com", # optional
"plan_id": "plan-id", # optional
"custom_start": "2024-01-01T00:00:00.000Z" # optional
})
```
#### `users.get(user_id, options=None)`
Gets a specific user.
#### `users.update(user_id, data, options=None)`
Updates a user.
#### `users.delete(user_id, options=None)`
Deletes a user.
#### `users.get_usage(user_id, options=None)`
Gets user usage.
#### `users.get_keys(user_id, options=None)`
Gets all API Keys for a user.
#### `users.create_key(user_id, data, options=None)`
Creates a new API Key for a user.
```python
key = await limitly.users.create_key(123, {
"name": "API Key for John"
})
```
## 🛠️ Error Handling
The SDK throws specific errors that you can catch:
```python
from limitly import Limitly, LimitlyError
try:
result = await limitly.validation.validate(
"invalid_api_key",
"/api/users",
"GET"
)
except LimitlyError as error:
print(f"Limitly error: {error.message}")
print(f"Status code: {error.status_code}")
print(f"Full response: {error.response}")
except Exception as error:
print(f"Unexpected error: {error}")
```
## 🔍 Advanced Examples
### FastAPI Middleware
```python
from fastapi import FastAPI, HTTPException, Request
from limitly import Limitly
app = FastAPI()
limitly = Limitly(api_key=os.getenv("LIMITLY_API_KEY"))
@app.middleware("http")
async def limitly_middleware(request: Request, call_next):
api_key = request.headers.get("authorization", "").replace("Bearer ", "")
if not api_key:
raise HTTPException(status_code=401, detail="API Key required")
try:
result = await limitly.validation.validate(
api_key,
request.url.path,
request.method
)
if not result.success:
raise HTTPException(
status_code=429,
detail={
"error": "Rate limit exceeded",
"details": result.details
}
)
response = await call_next(request)
return response
except LimitlyError as error:
print(f"Validation error: {error}")
raise HTTPException(status_code=500, detail="Internal error")
```
### Usage Monitoring
```python
# Monitor API Key usage
async def monitor_usage():
keys = await limitly.api_keys.list()
for key in keys.data or []:
usage = await limitly.api_keys.get_usage(key.id)
if usage.data and usage.data.percentage_used > 80:
print(f"⚠️ API Key {key.name} is at {usage.data.percentage_used}% usage")
```
### Automatic Plan Management
```python
# Create predefined plans
async def setup_default_plans():
plans = [
{
"name": "Basic Plan",
"description": "For new users",
"max_requests": 1000,
"request_period": "month"
},
{
"name": "Pro Plan",
"description": "For advanced users",
"max_requests": 10000,
"request_period": "month"
},
{
"name": "Enterprise Plan",
"description": "Unlimited",
"max_requests": -1,
"request_period": "month"
}
]
for plan_data in plans:
await limitly.plans.create(plan_data)
```
## 📦 Project Structure
```
src/limitly/
├── __init__.py # Main SDK class
├── client.py # Base HTTP client
├── types.py # Type definitions
└── modules/ # Specific modules
├── __init__.py
├── api_keys.py
├── plans.py
├── users.py
└── validation.py
```
## 🤝 Contributing
1. Fork the project
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
## 📄 License
This project is licensed under the MIT License. See the `LICENSE` file for details.
## 🆘 Support
- 📧 Email: hi@limitly.dev
- 💻 Limitly: https://www.limitly.dev
- 📖 Documentation: https://docs.limitly.com
- 🐛 Issues: https://github.com/limitlydev/limitly-python/issues
Raw data
{
"_id": null,
"home_page": null,
"name": "limitly-python",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Limitly Team <hi@limitly.dev>",
"keywords": "limitly, api, rate-limiting, api-keys, sdk, python",
"author": null,
"author_email": "Limitly Team <hi@limitly.dev>",
"download_url": "https://files.pythonhosted.org/packages/b7/0b/bb1dd35efd12a6e8d8fc0876f4201ff456d17f07444ea9eef60eadcdbf4f/limitly_python-1.0.3.tar.gz",
"platform": null,
"description": "# limitly-python\n\nOfficial Python SDK for [Limitly](https://www.limitly.dev) - API Key management, plans, users and request validation.\n\n## \ud83d\ude80 Installation\n\n```bash\npip install limitly-python\n```\n\n```bash\npoetry add limitly-python\n```\n\n```bash\npipenv install limitly-python\n```\n\n## \ud83d\udcd6 Basic Usage\n\n### Initialization\n\n```python\nfrom limitly import Limitly\n\nlimitly = Limitly(api_key=\"your_limitly_api_key\")\n```\n\n### Request Validation\n\nThe most common use case is validating your users' requests:\n\n```python\n# Validate a request\nresult = await limitly.validation.validate(\n \"user_api_key\",\n \"/api/users\",\n \"GET\"\n)\n\nif result.success:\n print(\"Request allowed\")\n print(f\"Current usage: {result.details.current_usage}\")\n print(f\"Limit: {result.details.limit}\")\nelse:\n print(f\"Request denied: {result.error}\")\n```\n\n### API Key Management\n\n```python\n# List all API Keys\nkeys = await limitly.api_keys.list()\nprint(f\"API Keys: {keys.data}\")\n\n# Create a new API Key\nnew_key = await limitly.api_keys.create(\n name=\"New API Key\",\n user_id=123\n)\nprint(f\"New API Key: {new_key.data.api_key}\")\n\n# Get usage for an API Key\nusage = await limitly.api_keys.get_usage(\"key-id\")\nprint(f\"Usage: {usage.data}\")\n```\n\n### Plan Management\n\n```python\n# Create a plan\nplan = await limitly.plans.create(\n name=\"Basic Plan\",\n description=\"Plan for basic users\",\n max_requests=10000,\n request_period=\"month\"\n)\n\n# Get plan usage statistics\nplan_usage = await limitly.plans.get_usage(plan.data.id)\nprint(f\"Plan usage: {plan_usage.data}\")\n```\n\n### User Management\n\n```python\n# Create a user\nuser = await limitly.users.create(\n name=\"John Doe\",\n email=\"john@example.com\",\n plan_id=\"plan-id\"\n)\n\n# Get user usage\nuser_usage = await limitly.users.get_usage(user.data.user_id)\nprint(f\"User usage: {user_usage.data}\")\n```\n\n## \ud83d\udd27 Configuration\n\n### Configuration Options\n\n```python\nfrom limitly import Limitly\n\nlimitly = Limitly(\n api_key=\"your_limitly_api_key\",\n base_url=\"https://your-project.supabase.co/functions/v1\", # optional\n timeout=30 # optional, default: 30 seconds\n)\n```\n\n### Request Options\n\nYou can pass additional options to any method:\n\n```python\nresult = await limitly.api_keys.list(\n timeout=10,\n headers={\"X-Custom-Header\": \"value\"}\n)\n```\n\n## \ud83d\udcda Complete API\n\n### Request Validation\n\n#### `validation.validate(api_key, endpoint, method, options=None)`\nValidates a user request.\n\n```python\nresult = await limitly.validation.validate(\n \"user_api_key\",\n \"/api/users\",\n \"GET\"\n)\n```\n\n#### `validation.validate_request(data, options=None)`\nValidates a request with data object.\n\n```python\nresult = await limitly.validation.validate_request({\n \"api_key\": \"user_api_key\",\n \"endpoint\": \"/api/users\",\n \"method\": \"GET\"\n})\n```\n\n### API Keys\n\n#### `api_keys.list(options=None)`\nLists all API Keys.\n\n#### `api_keys.create(data, options=None)`\nCreates a new API Key.\n\n```python\nkey = await limitly.api_keys.create({\n \"name\": \"New API Key\",\n \"user_id\": 123, # optional\n \"plan_id\": \"plan-id\", # optional\n \"status\": \"active\" # optional\n})\n```\n\n#### `api_keys.get(key_id, options=None)`\nGets a specific API Key.\n\n#### `api_keys.update(key_id, data, options=None)`\nUpdates an API Key.\n\n#### `api_keys.delete(key_id, options=None)`\nDeletes an API Key (soft delete).\n\n#### `api_keys.regenerate(key_id, options=None)`\nRegenerates an API Key.\n\n#### `api_keys.get_usage(key_id, options=None)`\nGets usage statistics for an API Key.\n\n#### `api_keys.get_requests(key_id, options=None)`\nGets request history for an API Key.\n\n### Plans\n\n#### `plans.list(options=None)`\nLists all plans.\n\n#### `plans.create(data, options=None)`\nCreates a new plan.\n\n```python\nplan = await limitly.plans.create({\n \"name\": \"Basic Plan\",\n \"description\": \"Plan for basic users\",\n \"max_requests\": 10000,\n \"request_period\": \"month\", # 'day', 'week', 'month', 'year'\n \"is_active\": True\n})\n```\n\n#### `plans.get(plan_id, options=None)`\nGets a specific plan.\n\n#### `plans.update(plan_id, data, options=None)`\nUpdates a plan.\n\n#### `plans.delete(plan_id, options=None)`\nDeletes a plan.\n\n#### `plans.get_usage(plan_id, options=None)`\nGets usage statistics for a plan.\n\n#### `plans.get_users(plan_id, options=None)`\nGets all users assigned to a plan.\n\n#### `plans.get_keys(plan_id, options=None)`\nGets all API Keys assigned to a plan.\n\n### Users\n\n#### `users.list(options=None)`\nLists all users.\n\n#### `users.create(data, options=None)`\nCreates a new user.\n\n```python\nuser = await limitly.users.create({\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\", # optional\n \"plan_id\": \"plan-id\", # optional\n \"custom_start\": \"2024-01-01T00:00:00.000Z\" # optional\n})\n```\n\n#### `users.get(user_id, options=None)`\nGets a specific user.\n\n#### `users.update(user_id, data, options=None)`\nUpdates a user.\n\n#### `users.delete(user_id, options=None)`\nDeletes a user.\n\n#### `users.get_usage(user_id, options=None)`\nGets user usage.\n\n#### `users.get_keys(user_id, options=None)`\nGets all API Keys for a user.\n\n#### `users.create_key(user_id, data, options=None)`\nCreates a new API Key for a user.\n\n```python\nkey = await limitly.users.create_key(123, {\n \"name\": \"API Key for John\"\n})\n```\n\n## \ud83d\udee0\ufe0f Error Handling\n\nThe SDK throws specific errors that you can catch:\n\n```python\nfrom limitly import Limitly, LimitlyError\n\ntry:\n result = await limitly.validation.validate(\n \"invalid_api_key\",\n \"/api/users\",\n \"GET\"\n )\nexcept LimitlyError as error:\n print(f\"Limitly error: {error.message}\")\n print(f\"Status code: {error.status_code}\")\n print(f\"Full response: {error.response}\")\nexcept Exception as error:\n print(f\"Unexpected error: {error}\")\n```\n\n## \ud83d\udd0d Advanced Examples\n\n### FastAPI Middleware\n\n```python\nfrom fastapi import FastAPI, HTTPException, Request\nfrom limitly import Limitly\n\napp = FastAPI()\nlimitly = Limitly(api_key=os.getenv(\"LIMITLY_API_KEY\"))\n\n@app.middleware(\"http\")\nasync def limitly_middleware(request: Request, call_next):\n api_key = request.headers.get(\"authorization\", \"\").replace(\"Bearer \", \"\")\n \n if not api_key:\n raise HTTPException(status_code=401, detail=\"API Key required\")\n \n try:\n result = await limitly.validation.validate(\n api_key,\n request.url.path,\n request.method\n )\n \n if not result.success:\n raise HTTPException(\n status_code=429,\n detail={\n \"error\": \"Rate limit exceeded\",\n \"details\": result.details\n }\n )\n \n response = await call_next(request)\n return response\n except LimitlyError as error:\n print(f\"Validation error: {error}\")\n raise HTTPException(status_code=500, detail=\"Internal error\")\n```\n\n### Usage Monitoring\n\n```python\n# Monitor API Key usage\nasync def monitor_usage():\n keys = await limitly.api_keys.list()\n \n for key in keys.data or []:\n usage = await limitly.api_keys.get_usage(key.id)\n \n if usage.data and usage.data.percentage_used > 80:\n print(f\"\u26a0\ufe0f API Key {key.name} is at {usage.data.percentage_used}% usage\")\n```\n\n### Automatic Plan Management\n\n```python\n# Create predefined plans\nasync def setup_default_plans():\n plans = [\n {\n \"name\": \"Basic Plan\",\n \"description\": \"For new users\",\n \"max_requests\": 1000,\n \"request_period\": \"month\"\n },\n {\n \"name\": \"Pro Plan\",\n \"description\": \"For advanced users\",\n \"max_requests\": 10000,\n \"request_period\": \"month\"\n },\n {\n \"name\": \"Enterprise Plan\",\n \"description\": \"Unlimited\",\n \"max_requests\": -1,\n \"request_period\": \"month\"\n }\n ]\n \n for plan_data in plans:\n await limitly.plans.create(plan_data)\n```\n\n## \ud83d\udce6 Project Structure\n\n```\nsrc/limitly/\n\u251c\u2500\u2500 __init__.py # Main SDK class\n\u251c\u2500\u2500 client.py # Base HTTP client\n\u251c\u2500\u2500 types.py # Type definitions\n\u2514\u2500\u2500 modules/ # Specific modules\n \u251c\u2500\u2500 __init__.py\n \u251c\u2500\u2500 api_keys.py\n \u251c\u2500\u2500 plans.py\n \u251c\u2500\u2500 users.py\n \u2514\u2500\u2500 validation.py\n```\n\n## \ud83e\udd1d Contributing\n\n1. Fork the project\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License. See the `LICENSE` file for details.\n\n## \ud83c\udd98 Support\n\n- \ud83d\udce7 Email: hi@limitly.dev\n- \ud83d\udcbb Limitly: https://www.limitly.dev\n- \ud83d\udcd6 Documentation: https://docs.limitly.com\n- \ud83d\udc1b Issues: https://github.com/limitlydev/limitly-python/issues \n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Official Python SDK for Limitly - API Key management, plans, users and request validation",
"version": "1.0.3",
"project_urls": {
"Bug Tracker": "https://github.com/limitlydev/limitly-python/issues",
"Documentation": "https://docs.limitly.com",
"Homepage": "https://github.com/limitlydev/limitly-python",
"Repository": "https://github.com/limitlydev/limitly-python"
},
"split_keywords": [
"limitly",
" api",
" rate-limiting",
" api-keys",
" sdk",
" python"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "fe7560196cccf0751874e71382cf65c0542ad3da97c5a48e5c3347675cc0515c",
"md5": "30f3cf75e436c70bba6b02e80c60c401",
"sha256": "03d12641daa3d6bb173735b6a2911227f4c6f42c7aba6cdcc5a2e87f6df1639c"
},
"downloads": -1,
"filename": "limitly_python-1.0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "30f3cf75e436c70bba6b02e80c60c401",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 15186,
"upload_time": "2025-08-04T09:51:29",
"upload_time_iso_8601": "2025-08-04T09:51:29.680270Z",
"url": "https://files.pythonhosted.org/packages/fe/75/60196cccf0751874e71382cf65c0542ad3da97c5a48e5c3347675cc0515c/limitly_python-1.0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "b70bbb1dd35efd12a6e8d8fc0876f4201ff456d17f07444ea9eef60eadcdbf4f",
"md5": "028137827b108cdb24648943a5ffa620",
"sha256": "9cca0fdcb28854eee8b43af8a893be635470b06799da51a91b16e5dcf73c260e"
},
"downloads": -1,
"filename": "limitly_python-1.0.3.tar.gz",
"has_sig": false,
"md5_digest": "028137827b108cdb24648943a5ffa620",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 16706,
"upload_time": "2025-08-04T09:51:30",
"upload_time_iso_8601": "2025-08-04T09:51:30.908635Z",
"url": "https://files.pythonhosted.org/packages/b7/0b/bb1dd35efd12a6e8d8fc0876f4201ff456d17f07444ea9eef60eadcdbf4f/limitly_python-1.0.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-04 09:51:30",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "limitlydev",
"github_project": "limitly-python",
"github_not_found": true,
"lcname": "limitly-python"
}