When to use one
Reach for a custom connector when:- You want to manage the connection yourself. Stand up your own pipeline against any source — including ones we support natively — and forward the same first-party event shapes (
email,page,message, …) to Adapter via/ingest/typed. Downstream processing — entity extraction, relationship resolution, the whole pipeline — runs identically. - The source isn’t on the supported providers list. Internal tools, legacy systems, anything you can hit with HTTPS — push it as a typed kind if it fits one of our shapes, otherwise as
custom. - You want to mix typed first-party data with arbitrary records that Adapter doesn’t otherwise see — system logs, ticket metadata, audit events. One connector can emit any combination of kinds it’s configured to accept.
Creating a connector
1
Open the Console
Go to Connectors in mind.adapter.com and switch to the Custom tab. Click Create connector.
2
Name it
Give it a display name and a source slug (auto-derived from the name, lowercase + hyphens). The slug is immutable after creation — it shows up in the event source (
custom:your-slug) and the storage path. Pick something descriptive.3
Pick accepted kinds
Select which first-party event types this connector may emit (
email, page, message, calendar, issue, or generic custom). Selecting none means all kinds are accepted. Anything outside the list is rejected with a 400.4
Save the connector ID
The console shows the
connector_id. Copy it — you’ll need it in the ingest endpoint paths below.5
Create an API key
Create an API key under Settings → API keys and store it securely — the secret is shown only once. See API keys for the full flow. Use this
pk_live_… key as the bearer token when calling the ingest endpoints.Pushing data
Each connector exposes four ingest endpoints under/v1/custom-connectors/{connector_id}. All require Authorization: Bearer pk_live_….
Typed events (recommended)
Use the typed path when your data fits one of Adapter’s first-party shapes (email, page, etc.). Adapter applies the same processing as native connectors — entity extraction, relationship resolution, the works.
external_ids list — useful if you want to look up the resulting document later.
Generic events
When your data doesn’t fit a typed shape — free-text notes, log lines, custom records from a tool that doesn’t have an Adapter integration — use the generic/ingest endpoint. It stores the data field verbatim as a StandardCustom event with event_type: "adapter.data.custom".
Free text:
data field accepts any JSON value — it’s stored as-is. There’s no required shape, but using a stable key (e.g. text, body, content) makes downstream queries easier.
Custom record with structure:
LLM enrichment does not run on
/ingest (JSON-only). If you have a long blob of text and want Adapter to extract summary/key-facts from it, save it to a file and post via /ingest/upload — the enricher picks up text-based documents, PDFs, images, and Office docs.Binary uploads
For files (PDFs, images, Office docs, and text-based documents), use the multipart upload endpoint:enriched_content block with summary, extracted text, and key facts. Use /ingest/upload (without /typed/) for binaries that don’t map to a typed kind.
Typed event shapes
Thepayload you send to /ingest/typed is validated against the corresponding type schema. Fields like source, user_id, container_id, and event_type are filled in automatically from the connector — you only supply the fields below. external_id is optional everywhere; Adapter generates one if you omit it. timestamp (ISO 8601) is also optional and defaults to ingest time.
email
page
For documents — Notion pages, Confluence pages, internal wikis, PDFs uploaded as kind=page.
message
For chat / Slack-like messages.
calendar
Provide either the
_time pair (timed) or the _date pair (all-day), not both.
issue
For tickets — Linear, Jira, GitHub issues, internal tracker rows.
custom
Escape hatch for data that doesn’t fit any typed shape. The whole data payload is stored verbatim.
You can also send
custom via the simpler /ingest endpoint (no kind field required) — see Generic events above.
Event metadata
Every event carries ametadata field — a flat string-to-string key/value map. Set it in two places; the two get merged at ingest time.
Connector-level metadata
Setmetadata on the connector to apply it to every event the connector emits. Useful for source-environment markers (env, region, tenant), data lineage (pipeline, version), or anything that’s constant for the connector’s lifetime.
PATCH /v1/custom-connectors/{connector_id} — changes apply to events ingested after the patch lands. Previously ingested events keep the metadata they had at the time.
Per-item metadata
Setmetadata on an individual ingest item to apply it to that event only. Useful for per-batch markers, request-correlation IDs, or anything that varies between calls.
/ingest and /ingest/typed.
Shape
Keys and values are strings. Non-string values are rejected at the API boundary. If you want to express a label-like marker without a meaningful value, use the key as the label and"true" as the value (e.g. { "urgent": "true" }). This shape keeps the field cleanly queryable once retrieval-side filtering ships.
Merge rules
When both are present, per-item metadata overrides connector metadata on key conflict. Disjoint keys merge.Where metadata is visible
The merged map lands onevent.metadata — a top-level field on every event. That matters because the event’s raw blob is stripped before delivery to subscribers and trigger routing, but metadata is not. Practically:
- Trigger rules and webhook subscribers see
metadataon the payload they receive. - Stored canonical documents (in object storage) carry the full
metadata. - Retrieval via
/v1/knowledge/searchand/v1/knowledge/ask— pass ametadataobject to restrict results to evidence carrying ALL the given key/value pairs (AND-of-exact-match). Max 20 keys, string values only. The same filter applies to/ask: it scopes every search the agent runs and rejects out-of-scope document reads, so the answer can only be grounded in matching evidence.
Looking at ingested data
Each connector card in the console has a View Data button that expands to show document counts per resource. Counts update as data lands; if they ever drift, the recovery path is to re-ingest or contact support.Tips
external_idis optional — Adapter generates one if you omit it. Provide your own when you want idempotent re-ingest (re-posting the sameexternal_idoverwrites the document).- API key scope:
pk_live_…keys are tenant-scoped — one key works against any connector in your container. Rotate by creating a new key and revoking the old. - Deactivation stops new ingest but retains existing data.
What’s next
API reference
Full schema for the ingest endpoints.
Evidence types
The shape of typed first-party events.