Skip to content

API Reference

A concise map of the public API. Import the framework surface from endocore, the ORM from endocore.orm, and service integrations from their own endocore.extensions.* submodule (see API stability below for exactly what "public" means here).

endocore

Core

  • Application(app_dir=".", *, dev=False, default_version=None, max_body_size=…, openapi=None, openapi_title=…, ws_allowed_origins=None)openapi=None: serve /docs + /openapi.json only when dev=True; ws_allowed_origins=None: enforce same-origin on websocket handshakes outside dev=True
  • Request.method .path .path_params .query .headers .cookies, await .json() .body() .form() .files(), .stream(), .get_signed_cookie()
  • Response(content, status=200, headers=None, media_type=…, background=None).json() .text() .redirect() .no_content(), .set_cookie() .set_signed_cookie() .delete_cookie()
  • StreamingResponse(content, …)
  • WebSocket, WebSocketDisconnect, WebSocketManager
  • get_logger()

Testing

  • TestClient(app, *, base_url="http://testserver") — in-process ASGI client, no socket, no extra dependency
    • .get/.post/.put/.patch/.delete/.head/.options(path, *, params=None, json=None, data=None, headers=None, cookies=None)TestResponse
    • with TestClient(app) as client: runs the real ASGI lifespan (on_startup/on_shutdown execute for real)
    • client.websocket_connect(path, *, headers=None) → a context-managed session: .send_text/.send_bytes/.send_json/.receive_text/.receive_bytes/.receive_json/.close()
  • TestResponse.status_code .headers .content .text .json() .cookies
  • WebSocketDisconnectError(code) — raised by a websocket_connect() session when the server closes or never accepts the connection
  • See Testing your app

Dependency injection & config

  • Depends(dependency)
  • Settings, env(name, default=None, cast=None), load_dotenv(path=".env", *, override=False)

Cache

  • configure_cache(backend="memory"|"redis", …), get_cache(alias="default"), cached(ttl=None, …)

HTTP exceptions

  • HTTPError(status, detail), BadRequest, Unauthorized, Forbidden (PermissionDenied), NotFound, MethodNotAllowed, Conflict, PayloadTooLarge, UnprocessableEntity, TooManyRequests

Data structures

  • QueryParams, FormData, UploadFile

Auth & passwords

  • login(request, pk), logout(request), user_id(request), require_user_id(request) — DI-dependency (401 for anonymous)
  • hash_password(pw), verify_password(pw, stored), needs_rehash(stored)

endocore.middleware

  • logging_middleware
  • cors_middleware(...), security_headers_middleware(...), gzip_middleware(...), proxy_headers_middleware(...), ip_allowlist_middleware(allowed=[...]), rate_limit_middleware(...), timeout_middleware(...), csrf_middleware(secret), session_middleware(secret, cookie_name="session", max_age=…, secure=False)
  • metrics_middleware(registry=None) — Prometheus, needs pip install endocore[metrics]; see Metrics
  • tracing_middleware(tracer=None) — OpenTelemetry, needs pip install endocore[otel]; see Tracing

endocore.orm

Models & fields

  • Model, fields.* (see Fields), get_models()
  • Instance methods: save(update_fields=None) delete() refresh_from_db() full_clean()
  • Async twins: await instance.asave(update_fields=None) .adelete() .arefresh_from_db() — threadpool-offloaded by default; see Native async for the opt-in async_native=True driver-native path (PostgreSQL only)

Connections & schema

  • configure(backend=…, alias="default", pool_size=…, pool_timeout=30, async_native=False, **params), connect(...), get_connection(alias), atomic(alias="default"), aatomic(alias="default"), close_all(), aclose_all()
  • create_all(*models), create_table(model), create_through_tables(model), drop_table(model)

Queries

  • Model.objects (Manager) → QuerySet
  • Q, F, Count, Sum, Avg, Min, Max
  • QuerySet: filter exclude get first last count exists all none order_by values values_list distinct only defer annotate select_related prefetch_related create bulk_create update bulk_update delete get_or_create update_or_create in_bulk aggregate earliest latest
  • Async twins (same names, a-prefixed): aget acreate acount aexists afirst alast alist aupdate adelete abulk_create abulk_update ain_bulk aaggregate aget_or_create aupdate_or_create + async for row in queryset

Migrations

  • Migrator(models=None, using="default", directory="migrations")makemigrations(name, renames=None) makedatamigration(name) migrate(target=None) rollback(steps=1) showmigrations() sqlmigrate(name)

Files & storage

  • fields.FileField(upload_to=…, storage=None)
  • configure_storage(root, key=…), generate_key(), get_storage(), EncryptedFileSystemStorage, StorageError

Exceptions

  • ORMError, ConfigurationError, UnsafeIdentifierError, FieldError, DoesNotExist, MultipleObjectsReturned, PoolTimeoutError, ValidationError

endocore.extensions

Imported from the package root (from endocore.extensions import RedisExtension) or, for the two observability integrations, from their own submodule (from endocore.extensions.metrics import MetricsExtension) — both forms are public and stable.

  • Extension (base class: .setup(app), async .startup(), async .shutdown())
  • RedisExtension(url=…), redis_client(...)
  • CeleryExtension(...), celery_app(...)
  • EmailExtension(...), EmailClient
  • CacheExtension(backend=…)
  • MetricsExtension(), default_registry() — see Metrics
  • TracingExtension(exporter=None, service_name="endocore") — see Tracing

API stability

As of 1.0, the surface below is covered by semver — a minor/patch release won't rename, remove, or change the meaning of any of it:

  • Every name in endocore.__all__, endocore.orm.__all__, endocore.middleware.__all__, and endocore.extensions.__all__ (everything listed on this page).
  • The two observability extension classes' submodules (endocore.extensions.metrics, endocore.extensions.tracing) — imported by path rather than re-exported at the package root, but just as public.
  • The ASGI entry point (endocore.asgi:create_app), the endo CLI's subcommands and their documented flags, and the file-based routing conventions themselves (Api/, vN/, [param], Get.py/Post.py/..., Socket.py, Middleware/, Services/, Models/, extensions.py).
  • A Model subclass's declared fields, Meta options, and the query API above — the SQL each one compiles to may change (an index, a join strategy) but the Python-level contract won't.

Not covered by that promise — these can change in a minor release, because they were never the contract:

  • Anything under a module that isn't listed above, anything name-prefixed with _, and every _..._native method on QuerySet/Connection (the async_native=True internals — call the public a* methods instead).
  • Exact exception messages (match on the exception type, not the string).
  • The exact SQL/DDL emitted for a given operation.
  • Anything under endocore.cli.templates (the endo new/endo create scaffolding content) and the bundled example//demos/ apps.

Source is the deepest reference

EndoCore is small and readable. When in doubt, read the module — every public function has a docstring, and the package is designed to be understood end-to-end.