Documentation
Documentation

Overview

Spore docs

Start here

Getting startedInstall the CLIAuthentication and keys

Build

Search and filtersSegments and the loopEnrichment lifecycle

Recipes

Recipe: search to a live SegmentRecipe: enrich without a segmentRecipe: land your own research

Connect

Events

Account

Credits and billing

Reference

Conventions
API reference

Recipe: enrich without a segment

Run any tool against up to 50,000 specific Company targets you name outright — quote, launch, poll, read.

POST /api/v1/enrich accepts an explicit list of Company ids, so there is no population to import or narrow. The list contains between one and 50,000 opaque Company UUIDs held by your organization. A registry identifier is not a Company id, and a Company held only by another organization returns 404 not_found. A large list can make a multi-megabyte request body. The strict body is { tool, input, target, maxCredits, priority?, dryRun, workstreamId? }: priority is background, normal, or urgent (omitted means normal), and every authorized agent may choose any tier. Admission is priority-first for free slots; priority orders future free Run slots but never preempts a running Run; Urgent has no surcharge or cap. target is { companyIds }; repeated ids collapse, because one target creates one Run. input must satisfy the selected tool's schema, and maxCredits is required.

1. Read the Legal entity data

POST /api/v1/companies/legal-entity is the bulk paid read for existing Company-plane ids. It accepts at most 100 opaque Company UUIDs per call and charges one credit for each Legal entity the organization has not yet been granted. A grant is permanent: later reads of the same Legal entity do not charge again.

{
	"companyIds": ["8a7a0f13-fce0-4d97-a5f8-1950a49e7a63"],
	"maxCredits": 1
}
curl -X POST https://www.spore.ee/api/v1/companies/legal-entity \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: inline-legal-entity-1" \
  -d @company-legal-entity.json

The quote below also names a second verified Company whose Legal entity has not been read. It is eligible for a Run, but its first priced use must buy the permanent unlock.

2. Quote it

The selected domain-finder reads the Company's name, operating country, and primary Activity from each target's Core; the caller cannot send or override them. To supply extra material, set input.context to Catalog field references that resolve to each target's current Facts; otherwise its input is empty.

{
	"tool": "domain-finder",
	"intent": "Find domains for the shortlist",
	"input": {},
	"target": {
		"companyIds": [
			"8a7a0f13-fce0-4d97-a5f8-1950a49e7a63",
			"5c91df6b-3d6f-48e0-9da8-39d551f94a6b"
		]
	},
	"maxCredits": 5,
	"priority": "normal",
	"dryRun": true
}
curl -X POST https://www.spore.ee/api/v1/enrich \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: inline-domain-quote-1" \
  -d @enrich-quote.json

200:

{
	"dryRun": true,
	"tool": "domain-finder",
	"targeted": 2,
	"quote": {
		"runs": 4,
		"unlocks": 1,
		"total": 5
	},
	"refused": []
}

The dry run targets one Company unlocked by step 1 and one verified Company whose Legal entity is still locked. quote.runs prices their Runs; quote.unlocks buys the permanent right to read the locked Legal entity, once, inside this first priced request; quote.total is their sum. An unverified target has no Legal entity to unlock. A target missing required Core is refused at admission with missing_input: it gets no Run and costs nothing, while refused names the Company and missing slots. targeted and the quote count only admitted targets. If none can be served, the request returns HTTP 422 missing_input.

3. Launch it

Use the same body with dryRun: false. The new Idempotency-Key is required so a network retry cannot double-launch or double-charge. The accepted launch preserves the dry-run split.

{
	"tool": "domain-finder",
	"intent": "Find domains for the shortlist",
	"input": {},
	"target": {
		"companyIds": [
			"8a7a0f13-fce0-4d97-a5f8-1950a49e7a63",
			"5c91df6b-3d6f-48e0-9da8-39d551f94a6b"
		]
	},
	"maxCredits": 5,
	"priority": "normal",
	"dryRun": false
}
curl -X POST https://www.spore.ee/api/v1/enrich \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: inline-domain-1" \
  -d @enrich.json

201:

{
	"job": {
		"id": "51e40960-d578-42c6-812c-7c2e21cfc540",
		"organizationId": "00000000-0000-4000-8000-000000000010",
		"kind": "enrichment",
		"intent": "Find domains for the shortlist",
		"lifecycle": "waiting",
		"priority": "normal",
		"occupiedSlots": 0,
		"scopeType": "inline",
		"segmentId": null,
		"companyId": null,
		"targetCount": 2,
		"runs": {
			"waiting": 0,
			"queued": 0,
			"running": 0,
			"succeeded": 0,
			"failed": 0,
			"cancelled": 0
		},
		"runTotal": 0,
		"quotedCredits": 5,
		"maxCredits": 5,
		"workstreamId": null,
		"createdByUserId": null,
		"createdByApiKeyId": "00000000-0000-4000-8000-000000000011",
		"startedAt": null,
		"completedAt": null,
		"cancelRequestedAt": null,
		"errorCode": null,
		"errorMessage": null,
		"createdAt": "2026-08-12T09:27:37.564Z",
		"updatedAt": "2026-08-12T09:27:37.564Z"
	},
	"quote": {
		"runs": 4,
		"unlocks": 1,
		"total": 5
	},
	"targeted": 2,
	"refused": []
}

Keep job.id for polling. The Job's ordered target list is its frozen receipt; it does not depend on a legacy Segment snapshot. The job object is the canonical Job projection: use its intent, priority, target count, Run counts, and credit fields rather than rebuilding them from the launch input. job.quotedCredits equals quote.total.

4. Poll the launch

curl https://www.spore.ee/api/v1/enrichments/$LAUNCH_ID \
  -H "Authorization: Bearer $SPORE_API_KEY"

The launch is progress, not payload: read launch.lifecycle and launch.outcome, watch launch.completed climb to launch.targeted, and stop at a terminal lifecycle. The canonical Job's job.lifecycle uses completed_with_issues for a settled Job with failed or cancelled child Runs; the launch's own projection spells that state completed_with_errors. The enrichment's top-level lifecycle and outcome describe the polled row — see Enrichment lifecycle.

5. Read the answers

Because the priced launch permanently unlocked every admitted target, the results land as knowledge on each Company:

curl "https://www.spore.ee/api/v1/company?ids=8a7a0f13-fce0-4d97-a5f8-1950a49e7a63,5c91df6b-3d6f-48e0-9da8-39d551f94a6b" \
  -H "Authorization: Bearer $SPORE_API_KEY"

knowledge.fields["domain-finder"] holds each value with observedAt, stale, and sourceRefs — the enrichment ids behind it, each pollable at GET /api/v1/enrichments/{id} for the full run body. The company read is free.

Next

Keep the populationSearch the Commons, unlock the result, and read a live Segment.Enrichment lifecycleLifecycle, outcomes, partial failure, cancellation, and automatic refunds.

Recipe: search to a live Segment

Search the Commons, unlock the population, then read your Companies and a live Segment for free.

Recipe: land your own research

Declare what you want to know, record what your harness observed, and have Spore hold its shape.

On this page

1. Read the Legal entity data2. Quote it3. Launch it4. Poll the launch5. Read the answersNext