Ingest API
Use the Ingest API to submit URL or file sources from a server-side integration. For normal onboarding, start with the account page and CLI.
Base URL: https://api.marrow.id
| Operation | Method | Path |
|---|---|---|
| Preview or queue URL source | POST |
/v1/ingest/url |
| Preview or queue file source | POST |
/v1/ingest/file |
| List record processing jobs | GET |
/v1/ingest/jobs?limit=20 |
| Inspect record processing job | GET |
/v1/ingest/jobs/{jobId} |
| Delete a source and its records | DELETE |
/v1/sources/{sourceId} |
Direct HTTP integrations require an API key with scope ingest. The 1.0
CLI reads MARROW_API_KEY for product commands, including marrow ingest url <url>, marrow ingest file <path>, marrow ingest jobs list, and marrow ingest jobs show <job-id>. marrow auth login creates a separate
account-management session for key lifecycle work on macOS.
Both POSTs are dry-run by default (dryRun: true). Live source submission
requires dryRun: false, a datedAt value in YYYY-MM-DD form, and a
caller-owned idempotencyKey. Live writes return 202 Accepted with a queued
job that Marrow processes asynchronously.
URL Source Submission
Request
POST /v1/ingest/url
{
"url": "https://example.com/my-bio",
"dryRun": false,
"datedAt": "2026-05-12",
"idempotencyKey": "bio-2026-05-12"
}
| Field | Type | Default | Notes |
|---|---|---|---|
url |
string | http or https. Localhost and private addresses are blocked |
|
dryRun |
boolean | true |
When true, returns a plan and does not persist anything |
datedAt |
string | YYYY-MM-DD. Required for live source submission |
|
idempotencyKey |
string | Required for live submission. 8 ≤ length ≤ 160; an exact retry reuses the same key and returns the existing job |
Response: 200 OK Dry Run
{
"schemaVersion": "marrow-url-ingest-plan-v1",
"mode": "dry-run",
"plan": { "summary": "Preview of records Marrow would write." }
}
Response: 202 Accepted Live
{
"schemaVersion": "marrow-ingest-job-v1",
"mode": "queued",
"created": true,
"job": { "id": "5d2a…", "status": "queued", "kind": "url" }
}
created: false indicates the idempotencyKey already had a job; the existing job is returned.
Provider-backed previews and live source submissions count against the account ingest quota. When a preview runs provider extraction, Marrow reserves processing credits before the provider request. Queueing the exact preview plan reuses that extraction and its charge instead of charging a second time.
Queue responses include:
x-marrow-quota-metric: ingest
x-marrow-quota-daily-limit: <current daily limit>
x-marrow-quota-daily-remaining: <current daily remainder>
x-marrow-quota-monthly-limit: <current monthly limit>
x-marrow-quota-monthly-remaining: <current monthly remainder>
If the daily or monthly quota is exhausted, the API returns 429 with
error.code: "account_quota_exceeded". Reusing an idempotencyKey for an
already queued job returns that existing job and does not consume another quota
unit.
Read GET /v1/access with the same customer API key for its current quota and
credit authority. Use the headers on each live response for the remaining value
and reset time; examples here do not define an account entitlement.
Provider-backed dry-runs spend one ingest allowance unit, return credit headers,
and can return
account_credits_exhausted before extraction starts. A structural preview that
does not call a provider reports a zero credit cost and does not spend the
ingest allowance. If credits are exhausted while a queued live job prepares
paid processing, the job ends as failed with failure.retryable: false and a
public credit message. Private processing and ledger codes are not returned on
the job.
File Source Submission
Request
POST /v1/ingest/file
{
"filename": "source-note.md",
"contentType": "text/markdown",
"contentBase64": "IyBTb3VyY2UK",
"dryRun": false,
"datedAt": "2026-05-12",
"idempotencyKey": "source-note-2026-05-12"
}
Accepted content types are application/pdf, text/markdown, text/plain,
text/html, and application/json. Files may be up to 50 MB (50,000,000
bytes). Oversize uploads return 413 Payload Too Large.
Dry-run previews extract facts and links for sources up to about 384 KB of text. Larger sources preview quickly with document structure only — the response carries a warning saying so — and run full extraction during live processing, so live record counts exceed the structural preview. Live processing cost scales with source size and stops with a typed, actionable failure if account credits or the daily processing budget run out partway.
idempotencyKey works the same way as URL source submission.
Response
200 OK(dry-run) →marrow-file-ingest-plan-v1202 Accepted(live) →marrow-ingest-job-v1withmode: "queued"
Live file source submission stores the uploaded file, then queues the job.
List Source Processing Jobs
GET /v1/ingest/jobs?limit=20
{
"schemaVersion": "marrow-ingest-job-list-v1",
"jobs": [
{ "id": "5d2a...", "kind": "url", "status": "succeeded", "createdAt": "...", "completedAt": "..." }
],
"pagination": { "limit": 20, "returned": 1, "hasMore": false, "nextCursor": null }
}
Get Source Processing Status
GET /v1/ingest/jobs/{jobId}
{
"schemaVersion": "marrow-ingest-job-v1",
"job": {
"id": "5d2a...",
"kind": "url",
"status": "succeeded",
"attempts": 1,
"failure": null,
"createdAt": "...",
"completedAt": "..."
}
}
Terminal statuses are succeeded, failed, and quarantined. quarantined
means the ingest finished but will not be used for answers until source
ownership or account connection is reviewed.
Failed jobs include a public failure object with message, retryable, and
failedAt. When retryable is false, do not submit the source again yet.
Check account usage; if usage does not explain
the stop, keep the job id and contact hello@marrow.id.
Private provider and ledger details are not included in the public response.
Delete a source
Delete a source when its content should no longer be available to retrieval:
curl -sS -X DELETE "$MARROW_API_BASE_URL/v1/sources/<source-id>" \
-H "Authorization: Bearer $MARROW_API_KEY"
The response is an ingest job with kind: "source_deletion". Poll its job.id
through GET /v1/ingest/jobs/{jobId}. After the job succeeds, the source and
its derived records no longer appear in query results. Deleting a source does
not delete unrelated sources in the account.
Errors
| Code | error.code |
Reason |
|---|---|---|
| 400 | invalid_ingest_request |
Live source submission missing datedAt or unsupported source details |
| 401 | unauthorized |
Missing or invalid product credential |
| 403 | forbidden |
API key lacks scope ingest |
| 404 | not_found |
Job id does not exist for this account |
| 413 | payload_too_large |
File upload exceeded 50 MB (50,000,000 bytes) |
| 400 | validation_error |
Body or query failed validation |
| 402 | account_credits_exhausted |
Preview extraction needs more account credits |
| 402 | processing_budget_exceeded |
Preview extraction exceeds the per-request or daily provider budget |
| 502 | processing_interrupted |
Preview provider work was billed but did not finish |
| 502 | processing_outcome_unverified |
Preview provider outcome could not be verified safely |
| 502 | ingest_job_failed |
Preview processing could not safely produce a plan |
| 503 | credit_settlement_failed |
Preview charge could not be verified or recorded safely |
| 429 | account_quota_exceeded |
Provider-backed preview or live source submission quota exhausted |
| 429 | rate_limited |
Rate limit hit |
A failed provider-backed preview never returns a plan that can be queued.
Credit headers report any standing provider charge. Keep the request ID when
the error is processing_outcome_unverified or credit_settlement_failed;
contact support before submitting the same source again.
CLI mapping
Prefer these commands for normal CLI source setup:
marrow ingest url https://example.com/source-note --dry-run --dated-at 2026-05-12
marrow ingest url https://example.com/source-note --dated-at 2026-05-12 --idempotency-key source-note-2026-05-12
marrow ingest file ./source-note.md --dry-run --dated-at 2026-05-12
marrow ingest file ./source-note.md --dated-at 2026-05-12 --idempotency-key source-file-2026-05-12
marrow ingest jobs list --limit 5
marrow ingest jobs show <job-id>
These source setup commands print human-readable status by default. Add --json
when a programmatic integration needs the structured API response.