Skip to main content
Features answer the third of the three pricing questions — after what kind of files and how much content comes what you want to search by. Instead of choosing models or pipelines, you declare the capabilities you want — visual similarity (image_search), faces (faces), on-screen text (onscreen_text), document layout (document_layout) — and the platform resolves the implementation internally. Swapping or upgrading the models behind a feature never changes your config, your API calls, or your pricing. Every feature applies to a modality (the what kind of files question) and is billed in that modality’s natural unit (the how much question): Clustering and taxonomy enrichment are included on every modality at no additional charge. For rates, tiers, and how usage is billed, see Billing & Pricing.

Discover features

GET /v1/collections/features returns the live feature menu — modalities, units, feature keys, display names, and current rates. No authentication required. This endpoint is the source of truth: studio, the homepage pricing page, and the billing engine all read the same catalog.
Response abbreviated — the live payload covers all six modalities. Feature kind tells you how it’s priced:

Create a collection with features

Pass features: [...] to Create Collection. The platform resolves the pipeline, pins its version, and defaults the input wiring for you:
Both SDKs accept features on collection create — Python mixpeek>=1.3.29 (client.collections.create(...)) and JavaScript mixpeek>=0.81.28 (client.collections.createCollection({ createCollectionRequest: { ... } })). Set the namespace when you construct the client (Python namespace=, JS namespace:, or the MIXPEEK_NAMESPACE env var) — collection create is namespace-scoped and returns 403 without it. The feature_extractor field is a deprecated alias.

Default input wiring

Every organization’s scaffolded uploads bucket exposes one standard source property per modality — image, video, audio, pdf, content (text), and url (web). A features-based create maps the pipeline’s inputs to those properties automatically, so the collection is runnable with zero wiring. If your bucket uses different property names, the create returns a teaching 422 naming the fields that exist so you can rename the property — or fall back to explicit input_mappings via the advanced pipeline config.

Errors teach

Validation on the features path is designed for humans and agents guessing their way in — every rejection tells you what to do instead:
  • Unknown keyfeatures: ["face"] responds with the full list of valid feature keys (and reminds you about custom:<plugin>).
  • One pipeline per collection — some feature combinations need separate collections (e.g. a base feature plus a companion: true add-on). The error lists exactly which features group into which collection: create one collection per group over the same source bucket. Add-ons flagged companion: true in discovery always create a companion collection alongside the base.
  • features XOR feature_extractor — provide one or the other, never both.
  • Not yet available — feature keys that appear on the roadmap but haven’t shipped are rejected explicitly rather than silently ignored.

Custom features (bring your own)

Custom extractors you publish are your vocabulary — they stay explicitly named and are selected as custom:<plugin_name>:
Custom features are priced per unit from the compute profile the plugin declares — the same machinery that prices native features. See Custom Extractors.

Full resolution opt-out

By default, Mixpeek normalizes content once at ingest (video to a 720p mezzanine, images capped at ~1568px max edge, audio to 16kHz mono) — originals are always kept untouched in your bucket. If a workload needs extraction on the original resolution (fine print OCR, tiny logos), opt out per collection:
Full-res processing bills at a 2x multiplier on the modality’s base and add-on rates (full_res_multiplier in the pricing payload).

Chain collections (advanced)

Searching by one thing often produces content worth searching by another — e.g. search video by scenes, then feed those documents into a second collection to search the results by something else. Collection-to-collection pipelines do exactly this: a collection can read another collection’s documents as its source, forming a processing DAG. See Multi-Tier Feature Extraction. A feature_search stage needs a feature_uri — the exact vector index to search. You picked features by name; each one produces a vector index whose feature_uri looks like mixpeek://<extractor>@<version>/<model>.
The last segment is the embedding model name, not the literal word embedding. A wrong feature_uri (e.g. .../embedding) does not error — the stage matches nothing and silently returns 0 results (with a self-correcting warning in the response). Always use the exact string.
The reliable, version-proof way — read it from the collection. After processing, GET the collection and copy the URI; this always matches what you actually built, even if model versions change:
Common features → feature_uri (the exact string a fresh @v1 collection produces):
Video transcript search. video_search produces one blended scene embedding (gemini-embedding-2); the transcript rides along as a text payload field, not a separate searchable vector. To search a transcript as its own vector, add the multimodal_understanding feature with transcription enabled — it creates a second index mixpeek://multimodal_extractor@v1/multilingual_e5_large_instruct_v1. When in doubt, GET the collection and read the feature_uris it actually has.

Estimate before you run

POST /v1/organizations/billing/estimate quotes planned ingestion using the same rating engine that bills you — the quote and the charge can’t disagree:
Base features are quoted automatically per the modality of each item — you only list add-ons. Unknown MIME types quote at the cheapest band rather than failing (be forgiving is a design rule here).

How this relates to extractors

Under the hood every feature resolves to an extraction pipeline, and custom extractors let you register your own. But built-in extractor names are no longer part of the public API surface — they remain accepted in configs only as deprecated aliases. If you have existing configs using feature_extractor, see the migration guide; for advanced pipeline knobs (input mappings, field passthrough, parameters), see Pipeline Configuration.