HTTP API
The public HTTP API accepts JSON and returns JSON. Browser-callable routes use project write-key authentication and origin checks.
Base URL:
https://app.seedy-pea.com
Common request fields:
| Field | Description |
|---|---|
project_id |
Project id, for example proj_.... |
write_key |
Project write key. |
anonymous_id |
Visitor id for anonymous profile routing. |
profile_ref |
Optional explicit profile reference on profile, delete, and decision routes. |
If a project has an origin configured, the request Origin header must match it.
POST /v1/events
Append a customer event.
POST /v1/events
Content-Type: application/json
Origin: https://example.com
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123",
"type": "PageViewed",
"detail": {
"path": "/pricing"
}
}
Response:
{
"ok": true,
"event_id": "evt_...",
"profile_ref": "anonymous:proj_...:visitor_123"
}
Event types must match:
^[A-Za-z][A-Za-z0-9_.]{0,62}$
Most sp.* event types are reserved for trusted substrate machinery. Customer-allowed sp.* types are currently sp.consent.granted and sp.consent.revoked.
segment.<name>.entered and segment.<name>.exited are also reserved.
POST /v1/scores
Append an external model score as sp.model.scored.
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123",
"model_name": "founder_offer_lookalike",
"model_version": 4,
"target": "founder_offer_capture_goal",
"score": 0.73,
"reasons": [
{ "contributor": "neighbors", "weight": 0.73 }
]
}
Response:
{
"ok": true,
"event_id": "evt_...",
"scored_at": "2026-06-06T16:00:00.000Z",
"score": {
"model_name": "founder_offer_lookalike",
"score": 0.73,
"model_version": 4,
"target": "founder_offer_capture_goal"
}
}
model_name must be declared in the project's scoring topology. target and model_version default from that declaration when omitted. scored_at is optional, but must be an ISO timestamp when provided.
POST /v1/profile
Fetch the current profile fold for an anonymous id or explicit profile ref.
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123"
}
Response:
{
"ok": true,
"profile_ref": "anonymous:proj_...:visitor_123",
"fold": {
"profile_ref": "anonymous:proj_...:visitor_123",
"pageview_count": 3
},
"segments": [
{ "segment_name": "all" }
],
"tactics": {},
"imported_facts": []
}
POST /v1/profile/delete
Erase the profile addressed by anonymous_id or profile_ref.
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123"
}
Response:
{
"ok": true,
"profile_ref": "anonymous:proj_...:visitor_123",
"vault_shredded": true,
"profile_destroyed": true,
"receipt_event_id": "evt_..."
}
The seedypea-client forget() helper calls this route directly in direct mode. In edge mode, it calls your same-origin /sp/profile/delete proxy.
POST /v1/decide
Ask Seedy Pea what to show on a surface. This route can create experiment assignment facts.
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123",
"surface": "homepage_hero"
}
Response:
{
"ok": true,
"profile_ref": "anonymous:proj_...:visitor_123",
"surface": "homepage_hero",
"experiments": {
"homepage_hero_copy": {
"variant": "receipts_first"
}
}
}
POST /v1/experiment/expose
Record that an assigned variant was actually shown.
{
"project_id": "proj_...",
"write_key": "wk_...",
"anonymous_id": "visitor_123",
"experiment_name": "homepage_hero_copy",
"surface": "homepage_hero"
}
Response is the substrate exposure result from the profile.
Assignment and exposure are separate facts. Calling /v1/decide does not imply exposure.