limitly-python


Namelimitly-python JSON
Version 1.0.3 PyPI version JSON
download
home_pageNone
SummaryOfficial Python SDK for Limitly - API Key management, plans, users and request validation
upload_time2025-08-04 09:51:30
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
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"
}
        
Elapsed time: 1.65862s