Story API
Identity Resolution and Story Composition — transforms Business Context into Story Projections that Pulse and consumer apps use to render timelines.
Base: https://pbcp-api.pcampus.co
Story API returns business meaning — Context API returns platform state. Use Story API for Pulse, demos, and all end-user surfaces.
GET /v1/story/resolve?q={input}
Identity Resolution — accepts any input (phone, email, order ID, product name) and returns matching entity candidates.
Headers: x-tenant-id (required)
Query params
| Param | Required | Description |
|---|---|---|
q | Yes | Customer ID, phone, email, order ID, product ID/SKU, product name |
Response 200 — single match
{
"query": "0812345678",
"candidates": [
{
"entityType": "customer",
"entityId": "ent_abc123",
"label": "Somchai Jai-dee",
"confidence": 1,
"hint": "phone:exact"
}
]
}Response 200 — multiple matches
{
"query": "Vitamin C",
"candidates": [
{
"entityType": "product",
"entityId": "P-101",
"label": "Blackmores Vitamin C",
"confidence": 0.88,
"matchReason": "product_name"
},
{
"entityType": "product",
"entityId": "P-102",
"label": "Vistra Vitamin C",
"confidence": 0.88,
"matchReason": "product_name"
}
]
}After receiving candidates → select 1 candidate → call GET /v1/story/{entityType}/{entityId}
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | Empty q |
404 | NOT_FOUND | No evidence in tenant (business-safe message) |
GET /v1/story/{entityType}/{entityId}
Story Composition — compose and return a Story Projection for an entity.
Supported entityType: customer | order | product | session
Headers: x-tenant-id (required)
Response 200
{
"entityType": "customer",
"entityId": "ent_abc123",
"label": "Somchai Jai-dee",
"metadata": {
"composedAt": "2026-06-28T10:30:00.000Z",
"completeness": "full",
"evidenceCount": 14
},
"timeline": [
{
"stepId": "step_001",
"eventName": "customer.registered",
"occurredAt": "2026-01-15T08:00:00.000Z",
"label": "ลงทะเบียนเป็นลูกค้า",
"payload": { "channel": "line_oa" }
},
{
"stepId": "step_002",
"eventName": "order.completed",
"occurredAt": "2026-03-10T11:30:00.000Z",
"label": "ซื้อสินค้า ฿1,200",
"payload": { "orderId": "ORD-001", "total": 1200 }
}
],
"insights": [],
"recommendations": []
}insights and recommendations are populated when the Intelligence layer enriches — Core always returns []. See Intelligence API for enriched stories.
Response 200 — partial completeness
When partial evidence exists but is incomplete:
{
"entityType": "customer",
"entityId": "ent_abc123",
"metadata": {
"completeness": "partial",
"missingTypes": ["payment_context"]
},
"timeline": [...]
}Missing evidence does not cause an error — returns 200 with completeness: "partial".
Errors
| Status | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | Missing x-tenant-id or unsupported entityType |
404 | NOT_FOUND | No evidence for entity in tenant |
500 | INTERNAL | Story composition failed |
Usage pattern (Pulse)
// 1. User searches in Pulse search bar
const { candidates } = await pbcp.story.resolve({ q: '0812345678' })
// 2. Pick top candidate
const { entityType, entityId } = candidates[0]
// 3. Compose story for entity
const story = await pbcp.story.compose(entityType, entityId)
// 4. Render StoryTimeline component
<StoryTimeline steps={story.timeline} />Examples
# Resolve by phone
curl -s 'https://pbcp-api.pcampus.co/v1/story/resolve?q=0812345678' \
-H 'x-tenant-id: pharmacy-demo'
# Compose customer story
curl -s 'https://pbcp-api.pcampus.co/v1/story/customer/ent_abc123' \
-H 'x-tenant-id: pharmacy-demo'
# Compose order story
curl -s 'https://pbcp-api.pcampus.co/v1/story/order/ent_ord1001' \
-H 'x-tenant-id: pharmacy-demo'