v3

latestOpenAPI 3.1.02026-07-311,4541,5202.3 MB
spans

Bulk Create Spans

The single canonical mixin for bulk endpoints.

Every view in this codebase that processes a SET of items in one request (/api/.../bulk/, /.../bulk-create/, /.../bulk-delete/) MUST inherit this mixin. There is intentionally only one — strategy choice (per-item loop vs batched query vs async dispatch vs criterion-delete) lives in the SUBCLASS body of process_bulk, not in the class hierarchy. Helpers in utils/bulk/strategies.py cover the common strategies; subclasses can also implement custom logic.

Why a single mixin: see BE_conventions/bulk.md. Variation by strategy was the road we explicitly avoided.

Subclass contract (required): bulk_serializer_class — DRF serializer for the request body get_bulk_items(validated_data) -> list process_bulk(items, **ctx) -> BulkOperationResponse

Subclass contract (optional): bulk_max_size — default 500 get_bulk_context(request, validated_data) -> dict get_bulk_status_code(response) -> int

The mixin defines post() to call handle_bulk_request. DELETE-shaped bulk endpoints (criterion-based deletion) restrict http_method_names to ["delete", "options"] and define delete() that delegates to handle_bulk_request.

Status code policy (override get_bulk_status_code for custom): all-success → 200 partial-success → 207 all-failure → 400 over-limit → 422 (returned directly, never reaches process_bulk)

Usage::

class MyBulkView(BulkOperationMixin, JWTAndAPIKeyAuthenticationViewMixin, APIView):
    bulk_serializer_class = MyRequestSerializer
    bulk_max_size = 100

    def get_bulk_items(self, validated_data):
        return validated_data["items"]

    def process_bulk(self, items, **ctx):
        from utils.bulk.strategies import run_bulk_loop

        def handle(*, item, index):
            self._do_one(item, **ctx)

        return run_bulk_loop(items, process_item=handle, is_atomic=True)
post/api/request-logs/bulk/

Headers

Authorizationstring required

Use your Respan API key for Respan API authentication. Enter only the Respan API key value; clients send Authorization: Bearer <RESPAN_API_KEY>. For /api/responses, provider credentials such as Perplexity, OpenAI, or Azure OpenAI go in Settings -> Providers or respan_params.credential_override in the request body, not in this authentication field.

Response

No response body

SpansBulkCreateSpansResponse200 required

Empty response body