> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oneloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# FastAPI

<Icon icon="github" iconType="solid" color="#000000" /> [Github](https://github.com/oneloop-starter-kits/fastAPI)

The FastApi starter kit leverages the `oneloop-python` SDK under the hood, but provides a helpful middleware that can be used for verifying API keys.

You can fork the starter kit repo, or copy the middleware from it.

<Info>
  If you haven't already, [create an account](https://dashboard.oneloop.ai) with
  Oneloop. Here is the link to our [QuickStart Guide](/documentation/quickstart)
  to help you get started.
</Info>

## Installation

```bash theme={null}
pip install typing fastapi oneloop-python
```

<Info>
  To learn more about the this SDK, you can visit the [Python SDK
  documentation](/sdk/python).
</Info>

## Usage

### Middleware

Let's first add the middleware that will be used to verify the API key. This will save you from having to write the same code in every route.

```python middleware.py theme={null}
import json
from typing import List, TypedDict, Optional
from fastapi import Request, HTTPException
from oneloop_client.client import OneloopApi
from oneloop_client.types import VerifyApiKeyResponse, ErrorResponse

class ScopeObject(TypedDict):
    id: str
    create: Optional[bool]
    read: Optional[bool]
    update: Optional[bool]
    delete: Optional[bool]

oneloop = OneloopApi(token="your-oneloop-api-key")

def oneloop_middleware(scopes: List[ScopeObject] = []):
    async def middleware(request: Request):
        # Extract the authorization header
        auth_header = request.headers.get("authorization")
        if not auth_header:
            raise HTTPException(status_code=401, detail="Customer API key is missing")

        # Create the verify request
        verify_request = oneloop.verify_api_key(
            key=auth_header.replace("Bearer ", ""),
            requested_scopes=[
                {
                    "id": scope["id"],
                    "representation": scope["id"],
                    "read": scope.get("read", False),
                    "create": scope.get("create", False),
                    "update": scope.get("update", False),
                    "delete": scope.get("delete", False),
                }
                for scope in scopes
            ]
        )

        try:
            # Verify the API key
            verify_response: VerifyApiKeyResponse = oneloop.verify_api_key(verify_request)

            if verify_response.status != "VALID":
              raise HTTPException(status_code=401, detail=verify_response.status)

        except Exception as e:
            error = json.loads(e.body)
            code = error['error']['code']
            message = error['error']['message']
            raise HTTPException(status_code=code, detail=message)



    return middleware

```

### Authenticate the API key

Now, let's use the middleware in a FastApi route and authenticate the API key.

```python routes.py theme={null}
# Define your routes
@app.get("/", dependencies=[Depends(oneloop_middleware())])
async def read_root():
    return {"Hello": "World"}
```

### Checking for permissions

You can also check for permissions in your routes. Let's say you have a route that requires a specific read access for profile data.
You want to check if the API key has the required scope before returning the data. You can pass that scope to the middleware.

Let's modify the above route to check for `profile` read access.

```python routes.py theme={null}
# Define your routes and check for permissions
@app.get("/", dependencies=[Depends(oneloop_middleware([{"id": "profile", "read": True}]))])
async def read_root():
    return {"Hello": "World"}
```
