Skip to main content

jentic-problem-details (Python)

RFC 9457 Problem Details models for Jentic APIs.

Installation

pip install jentic-problem-details

For FastAPI integration:

pip install jentic-problem-details[fastapi]

Quick Start

Basic Usage

from jentic.problem_details import ProblemDetail, ErrorItem

# Create a problem detail response
problem = ProblemDetail(
    status=400,
    title="Bad Request",
    detail="The request body is missing required field 'name'.",
    instance="/v2/capability-sets",
    errors=[
        ErrorItem(
            detail="Field 'name' is required.",
            pointer="#/name"
        )
    ]
)

print(problem.model_dump_json(exclude_none=True))

FastAPI Integration

from fastapi import FastAPI, Request
from jentic.problem_details import (
    BadRequest,
    NotFound,
    ProblemDetailException,
    problem_detail_exception_handler,
)

app = FastAPI()

# Register the exception handler
app.add_exception_handler(ProblemDetailException, problem_detail_exception_handler)

@app.get("/users/{user_id}")
async def get_user(user_id: str):
    # Input validation
    if not user_id:
        raise BadRequest(
            detail="User ID is required",
            instance="/users",
            code="JENTIC-4001"
        )
    
    # Resource not found
    user = await db.get_user(user_id)
    if not user:
        raise NotFound(
            detail=f"User '{user_id}' not found",
            instance=f"/users/{user_id}"
        )
    
    return user

@app.post("/users")
async def create_user(request: Request):
    data = await request.json()
    
    # Validation with multiple errors
    errors = []
    if not data.get("name"):
        errors.append({"detail": "Field 'name' is required", "pointer": "#/name"})
    if not data.get("email"):
        errors.append({"detail": "Field 'email' is required", "pointer": "#/email"})
    
    if errors:
        raise BadRequest(
            detail="The request body is missing required fields",
            instance="/users",
            errors=errors
        )
    
    user = await db.create_user(data)
    return user

Response Format

All exceptions produce responses with Content-Type: application/problem+json:

{
  "type": "about:blank",
  "status": 400,
  "title": "Bad Request",
  "detail": "The request body is missing required fields",
  "instance": "/users",
  "errors": [
    {
      "detail": "Field 'name' is required",
      "pointer": "#/name"
    }
  ]
}

Available Exceptions

Exception Status Description
BadRequest 400 Client error (malformed syntax, invalid parameters)
Unauthorized 401 Authentication required or failed
Forbidden 403 Server refuses to authorize the request
NotFound 404 Resource does not exist
Conflict 409 Request conflicts with current state
ValidationError 422 Request is well-formed but semantically invalid
TooManyRequests 429 Rate limit exceeded
ServerError 500 Unexpected server error
ServiceUnavailable 503 Server temporarily unable to handle request

All exceptions extend ProblemDetailException which accepts:

  • detail (required): Human-readable explanation
  • type: URI identifying the problem type (default: "about:blank")
  • title: Short summary (default: standard HTTP phrase)
  • instance: Request path or URI reference
  • code: Provider-specific error code
  • errors: List of ErrorItem for granular validation errors
  • headers: Additional HTTP headers

Error Items

For validation errors with multiple fields, use the errors array:

from jentic.problem_details import ValidationError, ErrorItem

raise ValidationError(
    detail="Multiple validation errors occurred",
    instance="/api/resources",
    errors=[
        ErrorItem(detail="Must be a positive integer", parameter="limit"),
        ErrorItem(detail="Must be 'asc' or 'desc'", parameter="order"),
        ErrorItem(detail="Must be a valid email", pointer="#/email"),
        ErrorItem(detail="Authorization header is malformed", header="Authorization"),
    ]
)

Development

# Install dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type checking
mypy src/

Standards

License

jentic-problem-details is licensed under Apache 2.0 license. jentic-problem-details comes with an explicit NOTICE file containing additional legal notices and information.

Metadata

Release files for jentic-problem-details 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jentic-problem-details 1.0.1
File Size Uploaded
jentic_problem_details-1.0.1.tar.gz 10.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jentic-problem-details 1.0.1
File Interpreter ABI Platform
jentic_problem_details-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 22.7 kB

Release files / jentic_problem_details-1.0.1.tar.gz

Download URL jentic_problem_details-1.0.1.tar.gz
Size 10.2 kB
Tags Source
SHA-256 checksum
How to use checksums
709b53bf9c73a3541e3192a64efa110612735a0b5e4d32ba1ebe5d085a6edf18
BLAKE2b-256 checksum
How to use checksums
1a088967e9a483411dabb19a25950a7e2a8cf065fea3935d928ea33469aa1c57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 14, 2026.

Transparency log

Release files / jentic_problem_details-1.0.1-py3-none-any.whl

Download URL jentic_problem_details-1.0.1-py3-none-any.whl
Size 12.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
481b3ad268dacd471e9e12fe64624527cf3ef9f1002ba265676adef386d45ab0
BLAKE2b-256 checksum
How to use checksums
fccfbb3cf3f70f14986eda218aeb36c981016dd4de7cb5865cfc171087e62df7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page