Skip to main content
POST
/
v2
/
query
Query
curl --request POST \
  --url https://api.opennous.cloud/v2/query \
  --header 'Content-Type: application/json' \
  --data '
{
  "scope": {
    "kind": "<string>",
    "property": "<string>",
    "source": "<string>",
    "entity_id": "<string>",
    "since_days": 123,
    "limit": 123
  },
  "without": {},
  "return": "<string>",
  "question": "<string>",
  "budget_tokens": 123
}
'
Where /v2/context is one entity, query is many. Pull the last 30 days of email replies, all meetings in a property, every signal from a CRM — and let your agent reason over the corpus. Three composable powers cover most “find me X” questions without adding endpoints:
  1. return: 'entities' groups results by entity (one row per person/company), ranked by most-recent matching activity
  2. without subtracts a second scope from the first — for set-difference queries like “sent but no reply”
  3. rollups.by_value appears when scope.kind = 'state' — counts entities by current value (funnel reports)

Request

curl -X POST https://api.opennous.cloud/v2/query \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "scope": {
      "kind": "event",
      "property": "interaction.email_replied",
      "since_days": 7,
      "limit": 10
    },
    "return": "entities",
    "question": "Who are the hottest leads this week?"
  }'

Body

scope
object
required
Primary filter for the corpus.
without
object
Optional set-subtract filter — same shape as scope. Entities matching scope MINUS entities matching without. Use for “did X but not Y” questions.
return
string
default:"observations"
"observations" — one row per observation (the classic shape). "entities" — one row per entity, ranked by most-recent matching activity. Each row reports its match count + the most-recent matching observation.
question
string
Your analytical question. Echoed back in the response. When set (and without is not), enables semantic ranking via embeddings.
budget_tokens
number
Approximate token budget for item summaries.

Response

return: 'observations' (default)

{
  "scope": { ... },
  "mode": "structured",
  "return": "observations",
  "matched": 142,
  "returned": 50,
  "sampled": true,
  "items": [
    {
      "observation_id": "...",
      "entity_id": "...",
      "entity_name": "Sarah Chen",
      "when": "2026-05-21T15:00:00Z",
      "type": "interaction.email_replied",
      "source": "gmail",
      "summary": "Interested but budget waiting on Q3"
    }
  ],
  "rollups": {
    "by_type":   { "interaction.email_replied": 142 },
    "by_source": { "gmail": 120, "outlook": 22 }
  }
}

return: 'entities'

{
  "scope": { ... },
  "return": "entities",
  "matched": 47,
  "returned": 10,
  "items": [
    {
      "entity_id": "a1b2c3d4-...",
      "entity_name": "Sarah Chen",
      "matches": 4,
      "most_recent_at": "2026-05-21T15:00:00Z",
      "most_recent_type": "interaction.email_replied",
      "most_recent_source": "gmail",
      "most_recent_summary": "Interested but budget waiting on Q3"
    }
  ],
  "rollups": { ... }
}

rollups.by_value (when scope.kind = 'state')

{
  "scope": { "kind": "state", "property": "stage" },
  "rollups": {
    "by_type":   { "stage": 198 },
    "by_source": { "hubspot": 162, "agent": 36 },
    "by_value":  {
      "identified": 120,
      "aware":      45,
      "interested": 22,
      "evaluating":  8,
      "client":      3
    }
  }
}

Recipe book

The four most common “find me X” patterns:

🔥 Hottest leads — recent replies, grouped

{
  "scope": {
    "kind": "event",
    "property": "interaction.email_replied",
    "since_days": 7
  },
  "return": "entities",
  "limit": 10
}
Top 10 entities by most-recent reply.

❄️ Cooled in last 5 days — was active, went silent

{
  "scope":   { "kind": "event", "since_days": 30 },
  "without": { "kind": "event", "since_days": 5 },
  "return": "entities"
}
Entities with any activity in the last 30 days, minus those with any activity in the last 5 days.

📭 Sent without reply in last 5 days

{
  "scope":   { "kind": "event", "property": "interaction.email_sent",    "since_days": 5 },
  "without": { "kind": "event", "property": "interaction.email_replied", "since_days": 5 },
  "return": "entities"
}
Entities you sent to in the last 5 days, minus those who replied in the same window.

📊 Full funnel report

{
  "scope": { "kind": "state", "property": "stage" }
}
Read rollups.by_value for the stage distribution. Pair with since_days to bound the time window.

Pattern-finding belongs to the agent

The graph retrieves and shapes. Your agent does the reasoning. The four recipes above are the most common; combine scope + without + return + rollups.by_value for anything else. For your own GTM profile (ICP, pricing, etc.) use /v2/workspace/facts instead — query is for per-entity observations only.