Dedicated infrastructure only. These endpoints are served by dedicated Enterprise deployments — they are not exposed on the shared public API at api.mixpeek.com, where they return 404/405. See Custom Extractors → Availability. Contact your account team to provision a dedicated deployment.Because this surface isn’t in the shared OpenAPI, it isn’t part of the auto-generated API Reference. This page is the hand-maintained contract; the reference client is server/scripts/api/plugins.py.
Naming. On this surface, custom extractors are addressed as plugins: the path segment is /plugins, and a deployed extractor’s plugin_id is {name}_{version} with dots replaced by underscores — e.g. text_embed@1.0.0 → text_embed_1_0_0. All endpoints are namespace-scoped and take Authorization: Bearer $MIXPEEK_API_KEY.
Lifecycle: upload → deploy → search
The CLI (python server/scripts/api/plugins.py push / deploy) wraps these calls. The raw HTTP flow:
NS=ns_... # your namespace id
API=https://<your-dedicated-host>/v1
AUTH=(-H "Authorization: Bearer $MIXPEEK_API_KEY" -H "Content-Type: application/json")
# 1. Request a presigned upload URL (auto-bumps the patch version if you omit it)
UP=$(curl -s -X POST "$API/namespaces/$NS/plugins/uploads" "${AUTH[@]}" \
-d '{"name":"text_embed","version":"1.0.0","file_size_bytes":5000}')
UPLOAD_ID=$(echo "$UP" | jq -r '.upload_id')
PRESIGNED=$(echo "$UP" | jq -r '.presigned_url')
# 2. PUT the zipped extractor to S3
curl -s -X PUT "$PRESIGNED" -H "Content-Type: application/zip" --data-binary @text_embed.zip
# 3. Confirm — runs the security scan + manifest validation
curl -s -X POST "$API/namespaces/$NS/plugins/uploads/$UPLOAD_ID/confirm" "${AUTH[@]}" \
-d '{"message":"initial release"}'
# → { "success": true, "plugin_id": "text_embed_1_0_0", "validation_errors": [] }
# 4. Deploy (omit deployment_type for full deploy incl. realtime; batch_only skips the HTTP endpoint)
curl -s -X POST "$API/namespaces/$NS/plugins/text_embed_1_0_0/deploy" "${AUTH[@]}"
# 5. Poll deployment status until DEPLOYED
curl -s "$API/namespaces/$NS/plugins/text_embed_1_0_0/status" "${AUTH[@]}"
Once DEPLOYED, reference the extractor’s feature_uri in a collection’s feature_extractor and in retriever feature_search stages exactly as you would a built-in — see the end-to-end walkthrough.
| Deployment status | Meaning |
|---|
QUEUED / PENDING | Waiting in / triggered the deployment queue |
IN_PROGRESS | Blue-green rollout in progress |
DEPLOYED | Ready for real-time inference |
NOT_DEPLOYED | Batch-only mode |
FAILED | Check the error field |
Endpoint reference
All paths are prefixed with /v1/namespaces/{namespace_id}.
Upload & deploy
| Method | Path | Purpose |
|---|
POST | /plugins/uploads | Request a presigned upload URL. Body: {name, version?, file_size_bytes} → {upload_id, presigned_url, version} |
POST | /plugins/uploads/{upload_id}/confirm | Confirm the S3 upload; runs security scan + manifest validation. Body: {message?} → {success, plugin_id, validation_errors} |
POST | /plugins | Direct multipart upload (alternative to the presigned flow) |
POST | /plugins/{plugin_id}/deploy | Deploy or redeploy. Query: deployment_type=batch_only to skip the realtime endpoint |
POST | /plugins/{plugin_id}/undeploy | Tear down the deployment (keeps the version) |
GET | /plugins/{plugin_id}/status | Deployment status |
POST | /plugins/{plugin_id}/realtime/test | Invoke the deployed realtime.py endpoint with a test payload |
Discover & inspect
| Method | Path | Purpose |
|---|
GET | /plugins | List custom plugins in the namespace |
GET | /plugins/{plugin_id} | Plugin details (schemas, deployment + validation status) |
GET | /plugins/{plugin_id}/source | Download source files of the active version |
GET | /plugins/{plugin_id}/download | Presigned archive download URL |
GET | /plugins/available | Org-level plugins available to enable in this namespace |
Version management
| Method | Path | Purpose |
|---|
GET | /plugins/by-name/{slug}/versions | Version history with deploy timestamps + messages |
POST | /plugins/by-name/{slug}/rollback | Restore a previous version as active |
GET | /plugins/by-name/{slug}/diff?v1=1.0.0&v2=1.0.1 | Diff source files between two versions |
Org plugins & namespace config
| Method | Path | Purpose |
|---|
POST | /plugins/org/{plugin_id}/enable | Enable an org-level plugin in this namespace |
POST | /plugins/org/{plugin_id}/disable | Disable an org-level plugin in this namespace |
POST | /plugins/reconfigure | Reconfigure the namespace vector-store schema for a plugin’s features |
DELETE | /plugins/{plugin_id} | Delete a plugin version |
CLI equivalents
server/scripts/api/plugins.py is the maintained client for this surface (reads MIXPEEK_API_KEY, MIXPEEK_NAMESPACE, MIXPEEK_API_URL):
| CLI | Endpoint(s) |
|---|
push | POST /plugins/uploads → PUT → POST /plugins/uploads/{id}/confirm |
pull | GET /plugins/by-name/{slug}/versions → GET /plugins/{id}/source |
status | GET /plugins/by-name/{slug}/versions |
log | GET /plugins/by-name/{slug}/versions |
rollback | POST /plugins/by-name/{slug}/rollback |
diff | GET /plugins/by-name/{slug}/diff |
lint / test | offline — no API call (work on any plan) |
See Custom Extractors for the full authoring guide and Local Development for lint/test.