> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Extractor API (Dedicated Infrastructure)

> HTTP reference for the custom-extractor upload, deploy, real-time, and version-management endpoints — available on dedicated Enterprise deployments

> [!WARNING]
>
> **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](https://docs.mixpeek.com/docs/processing/custom-extractors.md#availability). [Contact your account team](https://mixpeek.com/contact) 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 `plugins.py`.

> [!NOTE]
>
> **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 plugins.py push` / `deploy`) wraps these calls. The raw HTTP flow:

```bash theme={null}
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](https://docs.mixpeek.com/docs/processing/custom-extractors.md#end-to-end-extractor-collection-retriever).

| 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

`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](https://docs.mixpeek.com/docs/processing/custom-extractors.md) for the full authoring guide and [Local Development](https://docs.mixpeek.com/docs/processing/custom-extractors.md#local-development) for `lint`/`test`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.