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

Segments and the loop

Name a live filter over your Companies, read its members, refine it, and use what you learn.

A search answers a question once. A Segment keeps the question: a name and a filter over Companies your organization owns. Membership is live — whichever Companies match when you ask — rather than a snapshot that can go stale.

1. Open the population door

A registry predicate can only select Companies whose Legal entities your organization has unlocked. Use the Commons' two-step search first: POST /api/v1/search evaluates the population, then POST /api/v1/search/{searchId}/unlock mints every matched Legal entity as a Company of your organization and unlocks it, 1 credit per Legal entity you have not unlocked before.

That boundary is deliberate. A verified-but-locked Company never appears in a Segment, so reading a Segment cannot reveal Legal entity data you have not paid for. Search and unlock are the population door; every Segment operation is free.

2. Name the live filter

POST /api/v1/segments stores a name and a filter, and nothing else. It does not evaluate the Commons or count the result.

{
	"name": "Estonian software, high ICP",
	"filter": {
		"type": "group",
		"logic": "AND",
		"children": [
			{
				"type": "rule",
				"fieldId": "core.country",
				"operator": "equals",
				"value": "EE"
			},
			{
				"type": "rule",
				"fieldId": "registry.revenueEur",
				"operator": "greaterThan",
				"value": 1000000,
				"params": { "years": [2024] }
			},
			{
				"type": "rule",
				"fieldId": "research.icp_score",
				"operator": "greaterThan",
				"value": 7
			}
		]
	}
}
curl -X POST https://www.spore.ee/api/v1/segments \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: segment-create-1" \
  -d @segment.json

A filter leaf names its origin in fieldId:

ReferenceOrigin
core.<field>The Company's Core, such as core.country or core.domain
<namespace>.<field>A Catalog field declared by your organization, such as research.icp_score
registry.<field>Legal entity data in the Commons, such as registry.revenueEur

Every name is validated against the organization's own generated vocabulary. An undeclared Catalog field, unknown Core field, or unavailable registry field is refused rather than silently matching nothing. GET /api/v1/catalog?section=filter reports the vocabulary the same organization can use.

3. Read the Segment and its members

GET /api/v1/segments/{segmentId} returns the resource — its id, name, filter, timestamps, and strong ETag. GET /api/v1/segments pages all your Segments newest first, so an agent resuming work finds them instead of re-deriving them.

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

curl "https://www.spore.ee/api/v1/segments?limit=50" \
  -H "Authorization: Bearer $SPORE_API_KEY"

Page the live population separately:

curl "https://www.spore.ee/api/v1/segments/$SEGMENT_ID/companies?limit=50" \
  -H "Authorization: Bearer $SPORE_API_KEY"

The response is { items, nextCursor, total }. items is one page, nextCursor is opaque and continues the read, and total is the exact size of the whole matching set. The filter is evaluated when you ask, so Companies entering or leaving the filter are reflected without a rebuild. Every read is free.

4. Refine the question

PATCH /api/v1/segments/{segmentId} changes the name, the filter, or both. Read the Segment first and send its current strong ETag in Spore-If-Match (the standard If-Match, like every standard conditional header, is refused on writes); a stale value is refused with the current Segment and ETag. Editing the filter changes membership immediately.

{
	"segmentId": "26ef456b-9a86-4e6f-bbe3-6a7050da23de",
	"name": "Estonian software, ICP over 8",
	"filter": {
		"type": "group",
		"logic": "AND",
		"children": [
			{
				"type": "rule",
				"fieldId": "core.country",
				"operator": "equals",
				"value": "EE"
			},
			{
				"type": "rule",
				"fieldId": "research.icp_score",
				"operator": "greaterThan",
				"value": 8
			}
		]
	}
}
curl -X PATCH https://www.spore.ee/api/v1/segments/$SEGMENT_ID \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H 'Spore-If-Match: "1"' \
  -H "Idempotency-Key: segment-update-1" \
  -d @segment-update.json

5. Land your own knowledge

POST /api/v1/record writes results your own systems produced onto a Company, under fields you declared first with POST /api/v1/namespaces:

{
	"companyId": "7f9c2a14-3b6e-4d51-9a2f-1c8e5b0d47a3",
	"fields": [
		{ "field": "icp.score", "value": 82 },
		{ "field": "icp.rationale", "value": "Series A, hiring SDRs" }
	]
}
curl -X POST https://www.spore.ee/api/v1/record \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: segment-record-1" \
  -d @record.json

The batch is all-or-nothing and free. Values are checked against their declared types. Once the Facts land, a Segment whose filter names those Catalog fields reflects them on its next member read.

6. Enrich the matching Companies

POST /api/v1/enrich accepts one or more Companies named by opaque UUID. Page the Segment's members, choose the Companies that need the tool, and submit those ids explicitly:

{
	"tool": "domain-finder",
	"intent": "Find domains for the matching Companies missing one",
	"input": {},
	"target": {
		"companyIds": [
			"8a7a0f13-fce0-4d97-a5f8-1950a49e7a63",
			"5c91df6b-3d6f-48e0-9da8-39d551f94a6b"
		]
	},
	"maxCredits": 500,
	"priority": "urgent",
	"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: segment-enrich-1" \
  -d @enrich.json

Enrichment is priced; reading the Segment before and after it is not. Facts produced by the tool can make a Company enter or leave the Segment on the next read, just as recorded Facts can.

7. Delete deliberately

Deletion is permanent and is refused unless the query says confirm=true. Company Facts are untouched: they belong to Companies, not to the Segment that selected them.

{
	"segmentId": "26ef456b-9a86-4e6f-bbe3-6a7050da23de",
	"confirm": "true"
}
curl -X DELETE "https://www.spore.ee/api/v1/segments/$SEGMENT_ID?confirm=true" \
  -H "Authorization: Bearer $SPORE_API_KEY" \
  -H "Idempotency-Key: segment-delete-1"

The whole cycle

search → search unlock → segment-create → page members → enrich or record → page members. The paid doors acquire Legal entity data or run tools; creating, listing, reading, editing, and deleting a Segment are free. The Segment always names the current question, and every member read answers it against the Companies your organization owns now.

Search and filters

The company filter AST, the field vocabulary that defines it, and how canonical hashing makes an identical search free for 24 hours.

Enrichment lifecycle

What a launch does after you start it: lifecycle, the five outcomes, polling, partial failure, cancellation, and automatic refunds.

On this page

1. Open the population door2. Name the live filter3. Read the Segment and its members4. Refine the question5. Land your own knowledge6. Enrich the matching Companies7. Delete deliberatelyThe whole cycle