On this page

Build a daily call list

The job: every morning, a ranked list of who to contact today, in the tool your reps already open.

Who this is for: any team doing outbound off inbound signal.

What it costs you: one scheduled script. No webhook, no state.


One call gets you the list

curl -s "https://app.signal.geysera.com/signal-api/v1/visitors?min_intent=60&page_size=100" \
  -H "Authorization: Bearer $SIGNAL_API_KEY"
{
  "visitors": [
    {
      "company_domain": "acme.com",
      "company_name": "Acme Corp",
      "classification": "lead",
      "intent_score": 82,
      "resolved_email": "dana@acme.com",
      "resolved_name": "Dana Cole",
      "resolved_title": "VP Engineering",
      "employer": null,
      "visit_count": 7,
      "first_visit_at": "2026-08-02T09:14:00Z",
      "last_visit_at": "2026-09-15T16:41:00Z",
      "is_locked": false
    }
  ],
  "total": 214,
  "page": 1,
  "page_size": 100
}

total is what your plan may resolve, not the raw row count. If you are near your cap it will be smaller than reality, and the list is still the best visitors — not an arbitrary slice.

Ranking it like a human would

intent_score alone puts a curious researcher above a returning buyer. What reps actually want is warm and moving:

from datetime import datetime, timezone

def rank(v):
    days_since = (datetime.now(timezone.utc)
                  - datetime.fromisoformat(v["last_visit_at"])).days
    recency = max(0, 30 - days_since) / 30          # 1.0 today, 0 a month ago
    depth = min(v["visit_count"], 10) / 10           # saturates; 40 visits is a bot
    return v["intent_score"] * (0.5 + 0.3 * recency + 0.2 * depth)

todays = sorted(visitors, key=rank, reverse=True)[:25]

Every term here is a judgement you should change. The point is that the ranking is yours and lives in twelve lines you can read.

Handing it to an LLM

Here are today's 25 highest-intent visitors:
{visitors_json}

Group them into: (1) call today, (2) email today, (3) leave alone. For each in
groups 1 and 2, give one sentence on why, citing a specific number from the
record. Put anyone in group 3 whose data does not justify contact, and say
what is missing.

Asking for group 3 explicitly is what stops a model finding a reason for all twenty-five.

What will go wrong

is_locked: true. Beyond your plan's monthly resolution cap, records come back locked — you can see that a visitor exists but not who. Filter them out of a call list rather than showing a rep a row they cannot action.

Null names and titles. resolved_name, resolved_title and employer are frequently null. Identification gives you an email reliably; the rest is enrichment and is not guaranteed. Write your templates to survive nulls.

The same person every day. Nothing here tracks who you already called. Keep your own contacted set, or use the assistant's set_visitor_contacted so the state lives with the visitor.


Next: write a first-touch email from what they read · export and keep in sync

This page is maintained next to the service it describes and rendered here. Read it as markdown if you are pointing an agent at it.