Skip to main content
POST
/
api
/
v3
/
search
curl --request POST \
  --url https://api.lighton.ai/api/v3/search \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "query": "authentication system JWT tokens",
  "max_results": 5,
  "workspace_id": [
    42
  ]
}
'
{
  "results": [
    {
      "chunk_id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "The indemnifying party shall hold harmless and indemnify the other party...",
      "score": 0.92,
      "scores": {
        "text": 0.91,
        "vision": null,
        "keyword": 0.43,
        "multivector": 0.78,
        "relevance": 0.95
      },
      "source": {
        "file_id": 512,
        "filename": "customer-nda.pdf",
        "title": "Customer NDA — Nimbus Labs",
        "mime_type": "pdf",
        "size_bytes": 482113,
        "page_start": 3,
        "page_end": 4,
        "total_pages": 12,
        "tags": [
          {
            "id": 7,
            "name": "confidential"
          }
        ],
        "content_types": [
          {
            "path": "legal:contract:nda",
            "label": "Non-Disclosure Agreement",
            "attribute_values": {
              "jurisdiction": {
                "value": [
                  "FR",
                  "US"
                ],
                "type": "multi-select"
              },
              "is_mutual": {
                "value": true,
                "type": "boolean"
              },
              "counterparty": {
                "value": "Nimbus Labs",
                "type": "text"
              }
            }
          }
        ],
        "external_metadata": null
      },
      "workspace": {
        "id": 42,
        "name": "Legal Team"
      }
    }
  ]
}

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

DRF serializer mixin providing content_type and attribute fields.

Compose into any request serializer via multiple inheritance::

class SearchRequestSerializer(FacetFilterFieldsMixin, serializers.Serializer):
query = serializers.CharField(...)
# content_type and attribute inherited from the mixin
query
string
required

Natural-language search query. Maximum 1500 characters.

Maximum string length: 1500
content_type
string[]

Filter by content type path. Multiple values are OR. Exact-or-subtree matching by default (e.g. legal matches legal, legal:contract). Wildcards: *contract* (contains), legal:contract* (prefix).

attribute
string[]

Filter by attribute value. Repeated attribute entries are ANDed; values inside one entry are ORed with | (pipe is the recommended OR delimiter — comma also works but can be ambiguous with multi-key values). Example: attribute=fiscal_year:2024|2025&attribute=status:active → (fiscal_year 2024 OR 2025) AND (status active). Formats: name (has any value), name:value (exact), name:>value / name:>=value (gt/gte), name:<value / name:<=value (lt/lte), name:prefix* (starts with, case-insensitive), name:*text* (contains, case-insensitive), name:a|b (OR). Smart dates: filing_date:2023 (year), filing_date:2023-06 (month). Type-aware: booleans (true/false), multi-select (membership check). Scoped: content_type(legal:compliance).regulation:AML.

max_results
integer
default:10

Maximum number of chunks to return after reranking. Range: 1–50.

Required range: 1 <= x <= 50
workspace_id
integer[]

Restrict search to these workspace IDs. Cannot combine with file_id.

tag_id
integer[]

Restrict to documents carrying any of these tag IDs (OR). Cannot combine with file_id.

file_id
integer[]

Restrict to specific file IDs. Cannot combine with workspace_id or tag_id.

mode
enum<string>
default:text

"text": hybrid keyword + vector search. "vision": VLM-embedded page image search.

  • text - text
  • vision - vision
Available options:
text,
vision
relevance_scoring
enum<string>

Controls the cross-encoder relevance scoring step. "scoring_and_filtering" (default): Score candidates for relevance and only return those above the quality threshold. When no candidate clears the threshold, the few best-scoring candidates are returned instead of an empty result; their scores.relevance is then below the usual threshold. "scoring_only": Score every candidate for relevance but return them all, even low-scoring ones. Useful for building your own filtering logic. "none": Skip the relevance scoring step and return all candidates unfiltered. Fastest option, useful when you handle scoring yourself. Omit the field for the default; send "none" to skip. Overrides skip_rerank when both are sent.

  • none - none
  • scoring_only - scoring_only
  • scoring_and_filtering - scoring_and_filtering
Available options:
none,
scoring_only,
scoring_and_filtering
skip_rerank
boolean

Deprecated — use relevance_scoring. true → relevance_scoring=none, false → relevance_scoring=scoring_and_filtering. Ignored when relevance_scoring is provided.

include_image
boolean
default:false

Append a base64-encoded page image to each result.

include_bboxes
boolean
default:false

Append merged bounding boxes (in PDF points, top-left origin) to each result so callers can overlay chunk highlights on PDF pages. PDF documents in text mode only — non-PDF and vision-mode results always return an empty list. Omitted from the response entirely when false.

Response

Ranked search results. Empty array if no documents match.

results
object[]
required

Ranked search results.

explain
object

Scoring breakdown. Present only when explain=true and SEARCH_EXPLAIN_MODE is enabled.