NEWVectors or files. Pick a path.Start →

    Changelog

    Release Notes

    New capabilities and performance improvements across the Mixpeek platform. Every entry links to relevant documentation and examples.

    August 2026

    APIFeature

    A batch tier that comes back empty now tells you which filter emptied it

    When a multi-tier batch produced nothing, the failure read "no extractors with documents to process ... upstream tiers produced no matching documents or input_mappings did not match any fields". That names two different causes and gives you the numbers for neither, so working out which one you hit meant reading logs you may not have. The counters that separate them were already being computed and then dropped before they reached you. They now travel with the failure: how many source documents were fetched, how many survived the source filter, and how many were missing the input fields your mapping asked for. A tier that empties because your filter matched nothing now looks different from one that empties because a field name does not line up.

    Batching docs
    APIPerformance

    Tier timings now separate engine execution from queueing and setup

    A tier's `started_at` was stamped before the job was submitted, so it bundled manifest building and submission in with the actual processing. If a tier took four minutes you could not tell whether the work took four minutes or the work took ninety seconds and the rest was overhead. The engine reports its own start and end times for every job, and those were being passed along correctly at each hop and then never written down. They are now persisted on the tier, so the time your data spent being processed is visible separately from the time spent getting it there.

    Batching docs
    EnginePerformance

    The iconik connector no longer starves itself under its own retries

    The rate limiter counted every attempt against the window, including the ones it turned away. With many workers polling at once, the retries filled the budget and left almost nothing for real requests, so a sync could crawl precisely when it was busiest. After twenty rejected polls a caller also slipped through unlimited, which meant the cap leaked under exactly the contention it exists to control, and it did so quietly. Only an admitted request now counts against the window, so a rejected poll costs nothing. The two conditions that used to pass in silence, exhausting the poll budget and losing the Redis the limiter depends on, are both logged as warnings.

    Integrations
    APIFeature

    You can now score precision, recall, F1 and F2 without setting up a retriever

    Evaluations were retriever-scoped: a run needed a retriever_id and executed a live retriever per query, scoring returned document ids against relevant ones. That covers retrieval quality and leaves out everything else. If you wanted to compare how two extraction models caption the same images, or check a set of predictions you had already computed, there was no path through the API at all. `POST /v1/evaluations/score` takes a `{predicted, ground_truth}` pair or an `items` batch, treats both sides as sets, and returns per-item scores plus the macro-average. No retriever, no namespace, nothing persisted. It runs the same Precision, Recall, F1 and F2 calculators the retriever evaluations use, so a number you get here matches the one you would get there.

    API reference
    StudioFeature

    Studio shows you what a feature actually is, instead of raw JSON

    A geospatial feature rendered as a map in two places and fell back to a JSON blob everywhere else. File types, document-model fields and other feature values were formatted per page, so the same value looked different depending on where you found it. Feature values now render through one component that infers what it is looking at and displays it accordingly: coordinates as a map, media as a preview, structured values as readable fields. Embeddings stay summarised by dimension count, because a few thousand floats are not something to render. It is live in the payload panel, the similar-documents view and the cluster visualization.

    Studio
    APIPerformance

    A feature_search stage that only filters now accepts pre_filters when you create it

    A feature_search stage can skip searching entirely and just filter, by leaving `searches` empty. Putting `pre_filters` in that stage's params was rejected with a 422 when you created the retriever or ran an ad-hoc execute, so the one shape where filtering is the whole job was the one you could not save. Those filters are now lifted to the stage's config before validation runs, so the stage builds and executes through the normal request path. Setting filters in both places is still fine: the config-level value is the canonical one.

    APIFeature

    Cancelling a batch, tier or job records who cancelled it and why

    A canceled batch carried no trace of where the cancel came from, so a deliberate API call read the same as a batch that had stopped on its own. Working out which one you were looking at meant reconstructing it from logs. Cancels now stamp `canceled_by`, `canceled_at`, `cancel_reason` and `cancel_source` onto the record, and each cancel endpoint takes an optional `reason` you can pass at the call. It applies to batch, tier and job cancels.

    Batching docs
    EnginePerformance

    Video and audio tasks clean up the source files they download

    The ffmpeg-backed tasks that process a video, generate a thumbnail or process audio each download a temporary copy of the source and were leaving it behind. On a long-lived processing worker those copies built up until the worker ran out of local disk and got evicted, which takes its in-flight work down with it. Each of these tasks now removes its temporary source once the work finishes. A file you supplied directly is left alone. If a sibling task is still reading the same source, it survives until that task is done with it.

    StudioFeature

    The namespace suggested at signup says where the suggestion came from

    New accounts get a suggested namespace marked with a chip reading only "Suggested", and the explanation sat in a tooltip you had to hover to find. Anyone who never hovered was told something had suggested their namespace and never what. The chip now reads "Suggested by our research" on the row itself, so the provenance is visible at a glance. Where we have a reason specific to your organisation, the tooltip still carries it.

    Studio
    StudioFeature

    The cost estimator has its own link, so you can be sent straight to it

    The usage calculator lives inside billing settings, which is reachable but not linkable: anyone helping you size a workload had to describe where to click. Billing settings now opens the estimator directly at /settings/billing?calculator=1, so a support reply, a docs page or a billing email can hand you the calculator itself rather than directions to it. An optional src parameter records which surface sent you, which is how we find out where people actually need it.

    Pricing
    APIFeature

    Paging through a document list returns each row once, instead of repeating some and skipping others

    Listing documents with an offset re-served rows it had already returned and silently dropped others: forty rows fetched across four pages came back as twenty-two unique documents and eighteen duplicates. The cause was an ordering mismatch rather than a merge bug. Each page was sorted for display after being read, and a sorted short page is not a prefix of the sorted longer one, so consecutive pages were cut from differently-ordered windows and overlapped at every boundary. Offset paging now reads in the underlying stream order, which is stable across page sizes, slices by position, and sorts only the slice it returns. Pages stay ordered for display and every row appears exactly once.

    Documents API
    APIFeature

    A feature_uri that does not exist now says so, instead of telling you your vectors are missing

    Asking a collection for a feature it does not expose used to land in the vectors-absent branch, so the answer came back as "this collection has no vectors, re-upsert your data". On a collection holding 359,202 vectors that answer was not merely unhelpful, it prescribed a full re-ingestion and named the real cause as ruled out. A confident wrong remedy is worse than silence: silence costs time, this cost a re-extraction and pointed away from the typo. The response now distinguishes the two, naming which features the collection actually exposes, and a collection with genuinely no declared indexes still reaches the original message.

    Retrievers
    APIFeature

    Asking for an edge type that is not there now warns, rather than returning a successful empty page

    A graph traversal filtered on edge type and returned HTTP 200 with zero documents in three different situations: the type was a typo, the type was real but matched nothing, or the data carried no edges at all. All three looked identical from the outside, so a misspelling read as an honest no-match. The traversal now records the edge types it actually walked past and reports the difference, so a request for a type that is not present says so and names what is present. The three empty cases each get their own explanation.

    Retrievers
    APIFeature

    New collections get a correctly named vector index instead of a doubled prefix

    Collections created on one path stored their vector index name with the prefix twice, as col_col_abc123 rather than col_abc123, because the name was built by prepending a prefix to an id that already carried one. Nothing broke: every reader takes the stored field rather than rebuilding the name, so existing indexes keep resolving and no migration is needed. New collections now get the correct name, which leaves a mixed population that is safe precisely because nothing derives the name from the id.

    APIFeature

    The deduplicate stage accepts `field` and `threshold`, not only the full spellings

    A deduplicate stage configured with `field` and `threshold` was refused at search time with "fields parameter is required when strategy=field", because the model wanted `fields` as a list and `similarity_threshold`. Studio generated the shorter spellings, so a retriever could be built in the UI and then fail every single query it ran. One customer had five retrievers in that state and was searching at zero. Both short forms now resolve to what they plainly mean, a string or a list works for `field`, and the explicit full spelling still wins wherever both appear. A config carrying neither spelling fails as before, with the message that tells you which one to add.

    PlatformFeature

    A task that cannot be routed is refused instead of sitting at PENDING forever

    When the lookup that decides which queue a task belongs on came back empty, usually a cache miss or a slow read, the task was published with no queue name at all. It landed on a default list that nothing consumes, so it was never picked up and never failed. The row stayed PENDING indefinitely and nothing was raised, which is indistinguishable from a job that is merely slow. The publish path now retries that lookup and refuses outright if it still cannot resolve, so an unroutable task surfaces as an error you can see and retry rather than as silence.

    Documentation
    APIFeature

    Clustering accepts `enrich_source`, the field name it reads back to you

    Fetching a cluster returned a field called `enrich_source`, while creating one required `enrich_source_collection`. Copying the name off a cluster you had just read meant the field was dropped on the way in, and enrichment quietly never ran. The run still finished as COMPLETED with its labeled clusters, and no source document carried any cluster fields, so nothing in the result told you what had gone missing. Create now accepts `enrich_source` as an alias for the same setting. Setting the canonical field to `false` still wins over an alias, so turning enrichment off keeps it off.

    APIFeature

    A clustering run submitted during an engine deploy now waits the deploy out

    Submitting a cluster while the engine was rolling hit a deploy lock that asks callers to wait 120 seconds, and the retry envelope gave up after roughly 130 seconds in total. Any submission landing in a real cluster roll ran out of attempts before the engine came back. The task document was then left at IN_PROGRESS with nothing ever moving it, because the code meant to record the failure could not be reached. Retries now start at a 120 second floor and stretch across about 44 minutes, which outlasts a roll, and a submission that genuinely exhausts them is written as FAILED so you can see it and send it again.

    Clusters
    APIFeature

    A domain that fails verification goes back to pending so you can retry it

    Custom domain verification retries DNS and TLS checks a few times before giving up. On three of the five paths that give up, including the NXDOMAIN case you hit whenever the record has not been created yet, the code that returns the domain to `pending` was unreachable. The domain stayed parked in a status it could not leave, so adding the DNS record afterwards changed nothing and the only way forward was to delete it and start again. All five paths now reset the row before they finish.

    Documentation

    Run the latest on your own files

    Everything above is live. Point Mixpeek at the storage you already have and search your video, images, audio, and documents through one API. Build starts at $25/mo for up to 1M vectors.