Skip to main content

A customizable exception handling library for FastAPI

Project description

APIException for FastAPI

PyPI version Documentation Downloads Python Versions License Code style: black Documentation

APIException is a fully extensible exception-handling library for FastAPI, designed to help you standardize error responses, manage custom error codes, and ensure predictable, well-documented APIs — from day one.

  • 🔒 Consistent JSON responses for both success and errors.
  • 📚 Beautiful Swagger/OpenAPI documentation with clear error cases.
  • ⚙️ Customizable error codes with BaseExceptionCode.
  • 🔗 Global fallback for unhandled server-side errors.
  • 🗂️ Use with multiple FastAPI apps.
  • 📜 Automatic logging of every exception detail.
  • ✔️ Production-ready with unit test examples.

· View on PyPI

· Full Documentation

Reading the full documentation is highly recommended — it’s clear, thorough, and helps you get started in minutes.


📦 Installation

pip install APIException==0.1.12

pip-install-APIException.gif


⚡ Quickstart

1️⃣ Register the Handler

from APIException import register_exception_handlers
from fastapi import FastAPI

app = FastAPI()
register_exception_handlers(app)  # uses ResponseModel by default

# Use raw dict instead:
# register_exception_handlers(app, use_response_model=False)

🔍 See It In Action

from fastapi import FastAPI, Path
from APIException import APIException, ExceptionStatus, register_exception_handlers, ResponseModel, APIResponse, BaseExceptionCode
from pydantic import BaseModel

app = FastAPI()

# Register exception handlers globally to have the consistent
# error handling and response structure
register_exception_handlers(app=app)

# Create the validation model for your response
class UserResponse(BaseModel):
    id: int
    username: str

# Define your custom exception codes extending BaseExceptionCode
class CustomExceptionCode(BaseExceptionCode):
    USER_NOT_FOUND = ("USR-404", "User not found.", "The user ID does not exist.")
    INVALID_API_KEY = ("API-401", "Invalid API key.", "Provide a valid API key.")
    PERMISSION_DENIED = ("PERM-403", "Permission denied.", "Access to this resource is forbidden.")


@app.get("/user/{user_id}",
    response_model=ResponseModel[UserResponse],
    responses=APIResponse.custom(
        (401, CustomExceptionCode.INVALID_API_KEY),
        (403, CustomExceptionCode.PERMISSION_DENIED)
    )
)
async def user(user_id: int = Path()):
    if user_id == 1:
        raise APIException(
            error_code=CustomExceptionCode.USER_NOT_FOUND,
            http_status_code=401,
        )
    data = UserResponse(id=1, username="John Doe")
    return ResponseModel[UserResponse](
        data=data,
        description="User found and returned."
    )

user{user_id}.gif


2️⃣ Raise an Exception

from APIException import APIException, ExceptionCode, register_exception_handlers
from fastapi import FastAPI
app = FastAPI()

register_exception_handlers(app)

@app.get("/login")
async def login(username: str, password: str):
    if username != "admin" or password != "admin":
        raise APIException(
            error_code=ExceptionCode.AUTH_LOGIN_FAILED,
            http_status_code=401
        )
    return {"message": "Login successful!"}

3️⃣ Use ResponseModel for Success Responses

from APIException import ResponseModel, register_exception_handlers
from fastapi import FastAPI
app = FastAPI()

register_exception_handlers(app)

@app.get("/success")
async def success():
    return ResponseModel(
        data={"foo": "bar"},
        message="Everything went fine!"
    )

Response Model In Abstract:

response_model.gif


🧩 Custom Error Codes

Always extend BaseExceptionCode — don’t subclass ExceptionCode directly!

from APIException import BaseExceptionCode

class CustomExceptionCode(BaseExceptionCode):
    USER_NOT_FOUND = ("USR-404", "User not found.", "User does not exist.")
    INVALID_API_KEY = ("API-401", "Invalid API key.", "Key missing or invalid.")

And use it:

from APIException import APIException

raise APIException(
    error_code=CustomExceptionCode.USER_NOT_FOUND,
    http_status_code=404
)

⚙️ Override Default HTTP Status Codes

from APIException import set_default_http_codes

set_default_http_codes({
    "FAIL": 422,
    "WARNING": 202
})

🌐 Multiple Apps Support

from fastapi import FastAPI
from APIException import register_exception_handlers

mobile_app = FastAPI()
admin_app = FastAPI()
merchant_app = FastAPI()

register_exception_handlers(mobile_app)
register_exception_handlers(admin_app)
register_exception_handlers(merchant_app)

📝 Automatic Logging

Every APIException automatically logs:

  • File name & line number

  • Error code, status, message, description

Or use the built-in logger:

from APIException import logger

logger.info("Custom info log")
logger.error("Custom error log")

✅ Testing Example

import unittest
from APIException import APIException, ExceptionCode, ResponseModel

class TestAPIException(unittest.TestCase):
    def test_api_exception(self):
        exc = APIException(error_code=ExceptionCode.AUTH_LOGIN_FAILED)
        self.assertEqual(exc.status.value, "FAIL")

    def test_response_model(self):
        res = ResponseModel(data={"foo": "bar"})
        self.assertEqual(res.status.value, "SUCCESS")

if __name__ == "__main__":
    unittest.main()

Run the Tests

  • To run the tests, you can use the following command in your terminal:
python -m unittest discover -s tests

🔗 Full Documentation

Find detailed guides and examples in the official docs.


📜 Changelog

v0.1.13 (2025-07-21)

Initial stable version

  • /examples/fastapi_usage.py has been updated.

  • 422 Pydantic error has been fixed in APIResponse.default()

  • Documentation has been updated.

  • Exception Args has been added to the logs.

  • Readme has been updated. New gifs have been added.

v0.1.12 (2025-07-14)

  • /examples/fastapi_usage.py has been updated.

  • 422 Pydantic error has been handled in register_handler

  • Documentation has been added.

  • use_fallback_middleware has been added.

v0.1.11 (2025-07-13)

  • Added CLI entrypoint (api_exception-info)

  • Stable test suite with FastAPI TestClient

  • Multiple app support

  • Raw dict or Pydantic output

  • Automatic logging improvements

v0.1.0 (2025-06-25)

🚀 Prototype started!

  • Project scaffolding

  • ResponseModel has been added

  • APIException has been added

  • Defined base ideas for standardizing error handling


License

This project is licensed under the MIT License. See the LICENSE file for more details. If you like this library and find it useful, don’t forget to give it a ⭐ on GitHub!

Contact

If you have any questions or suggestions, please feel free to reach out at ahmetkutayural.dev

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

APIException-0.1.13.tar.gz (14.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

apiexception-0.1.13-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

APIException-0.1.13-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file APIException-0.1.13.tar.gz.

File metadata

  • Download URL: APIException-0.1.13.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.10

File hashes

Hashes for APIException-0.1.13.tar.gz
Algorithm Hash digest
SHA256 dfbdbe0fae692fb3a5093908551064bc83e19770ab3e3e92fde15f6b029f3641
MD5 5dfec0aa6a29250d1935170d441b2897
BLAKE2b-256 2a03a381577aec13fe1bcc38263302352102f91719acb68e75083ffcaeb8745c

See more details on using hashes here.

File details

Details for the file apiexception-0.1.13-py3-none-any.whl.

File metadata

  • Download URL: apiexception-0.1.13-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.10

File hashes

Hashes for apiexception-0.1.13-py3-none-any.whl
Algorithm Hash digest
SHA256 d586fc902a903b4aaf69d40219f40087485759850abeb361cc658858982bdbde
MD5 852d7a2883ab26eb8eb140183b8092d0
BLAKE2b-256 daec8f3cef26ff8341d389dceebcd387a537b1133f2f575e0c78a00b7270c358

See more details on using hashes here.

File details

Details for the file APIException-0.1.13-py3-none-any.whl.

File metadata

  • Download URL: APIException-0.1.13-py3-none-any.whl
  • Upload date:
  • Size: 17.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.10

File hashes

Hashes for APIException-0.1.13-py3-none-any.whl
Algorithm Hash digest
SHA256 c39e95241e5f5628e16a975c644067a011e59f96abc3c5a2e99ed9bf19f94ea0
MD5 c80220a4825f035060fada31b0f97011
BLAKE2b-256 209c58bfa6aee07bb80b2111d10979e02598566e0402da34a47c18b05ed7d993

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page