Skip to content
SSalesShiftDocs

Guide

Prospect to sequence

The whole loop in one page: find someone in the shared pool, reveal their details, turn them into a contact, put them in a sequence, and read the funnel back. Four surfaces — the CLI, Python, Go and TypeScript — doing the same six steps, with the real output from the run that produced this page.
Executed 2026-08-12api.vxcloud.iovxcli · Python · Go · TypeScript

The six steps

  1. 1

    Search the pool

    Cross-tenant, and masked. Costs nothing.
  2. 2

    Reveal one person

    Un-masks email, phone and LinkedIn together — one reveal, all three.
  3. 3

    Convert to a contact

    The only step that produces something mailable.
  4. 4

    Create a sequence

    Two touches, three days apart, stopping on reply.
  5. 5

    Activate and enrol

    Suppressed and unsubscribed contacts are skipped here, with a reason.
  6. 6

    Read the funnel

    Measured against tracking rows, not incremented counters.

With vxcli

The fastest way to see the whole thing work. Each block is a real command; the output beneath it is pasted.

1 — search the pool
vxcli salesshift leads search --title "engineer" --limit 5
Output
    Matches            13
    Sort (applied)     score desc
    Backend            go-node

  NAME                   TITLE                      COMPANY            LOCATION       SCORE
  Ingrid Beaumont        VP Engineering             Makersite          Edinburgh, GB     62
      dfa655ce-7fe3-5632-a7ae-9ed7d4cbefbe  i•••@makersite.de (masked — not revealed)  · unverified · phone×1
  Devon Delacroix        VP Engineering             Boast              Toronto, CA       60
      7f539023-7aad-581f-9e14-7a32e9ea4ca7  d•••@boast.ai (masked — not revealed)  · unverified · phone×1

  (masked) is not a real address — `vxcli salesshift leads reveal <pool-id>` spends one reveal.

  Next page: rerun with --cursor NTQ.c42ddbb5-4d55-5712-8b49-df7a20541461
Executed 2026-08-12 against https://api.vxcloud.io. Ids and counts are from that run; yours will differ.
2 — reveal
vxcli salesshift leads reveal 7f539023-7aad-581f-9e14-7a32e9ea4ca7 --yes
Output
  ! This will use up to 1 reveal(s) — you have 2499973 of 2500000 left this period.
  A person you have already revealed is free to reveal again.

  ▎ Revealed  ────────────────────────────────────────────────────
    Pool ID            7f539023-7aad-581f-9e14-7a32e9ea4ca7
    Email              [email protected]
    Phone              +1 416 8973 4254
    LinkedIn           https://www.linkedin.com/in/devon-delacroix-83
    Reveals used       27 / 2500000
    Remaining          2499973

  Revealing does not make this person mailable — only `leads convert` creates a Contact.
Re-executed 2026-08-13 against https://api.vxcloud.io. The allowance shown is this workspace's; yours comes from your own plan.

One reveal returned the address, the phone and the LinkedIn profile. They are not metered separately.

3 — save and convert
vxcli salesshift leads save 7f539023-7aad-581f-9e14-7a32e9ea4ca7
vxcli salesshift leads convert <lead-id>

# then confirm it is a contact, and therefore mailable
vxcli salesshift contacts list --q "Devon Delacroix"
4 — build a two-touch sequence
vxcli salesshift sequences create \
  --name "CLI parity — 2-touch intro" \
  --subject "{{first_name}}, quick question about {{company_name}}" \
  --body "<p>Hi {{first_name}},</p><p>We build and host the sending, the pool and the automation ourselves.</p>" \
  --delay-days 0

vxcli salesshift sequences add-step <sequence-id> \
  --subject "Re: {{company_name}}" \
  --body "<p>Bumping this once in case it slipped.</p>" \
  --delay-days 3
Output — sequences show
  ▎ Sequence  ────────────────────────────────────────────────────
    Name               CLI parity — 2-touch intro
    Status             DRAFT
    Stop on reply      true
    Send days          mon, tue, wed, thu, fri

  ▎ Steps (2)  ───────────────────────────────────────────────────
    +0d  email    {{first_name}}, quick question about {{company_name…
    +3d  email    Re: {{company_name}}
Executed 2026-08-12 against https://api.vxcloud.io. Ids and counts are from that run; yours will differ.

Delays are measured from the previous step, not from enrolment — so+3d means three days after touch one goes out.

5 — activate and enrol
vxcli salesshift sequences activate <sequence-id>
vxcli salesshift sequences enroll <sequence-id> --contacts <id>,<id>,<id>
vxcli salesshift sequences enrollments <sequence-id>
Output
  Active — due steps will dispatch.

  ✓ 3 enrolled · 0 skipped

  ACTIVE      [email protected]         step 1  —
  ACTIVE      [email protected]     step 1  —
  ACTIVE      [email protected]        step 1  —
Executed 2026-08-12 against https://api.vxcloud.io. Ids and counts are from that run; yours will differ.
6 — read the funnel
vxcli salesshift sequences analytics <sequence-id>
Output — a sequence that has really sent
  ▎ Sequence analytics  ──────────────────────────────────────────
    Enrolled           4
    Sent               8
    Opened             6 (75.0%)
    Clicked            0 (0.0%)
    Replied            0 (0.0%)
    Bounced            0 (0.0%)

  ▎ Per step  ────────────────────────────────────────────────────
    Step 1                     call      6 sent ·   0 opened ·  0 replied
    Step 2                     email     4 sent ·   3 opened ·  0 replied
    Wait 2d 4h                 delay     0 sent ·   0 opened ·  0 replied
    Step 4                     email     4 sent ·   3 opened ·  0 replied
Executed 2026-08-12 against https://api.vxcloud.io. Ids and counts are from that run; yours will differ.

Every counter there is measured against the email-tracking rows rather than incremented in place, which is why a step can show more sends than the step after it: enrolments that replied or bounced never reached the later touch.

The same flow in an SDK

Python, Go and TypeScript expose the same six calls. The Python block below is the one that produced the output underneath it.

Python
import vxsdk

c = vxsdk.Client.load_from_vxcli()
c.authenticate()
ss = c.salesshift

# 1-3 — find a contact that already exists, or convert one from the pool
page = ss.list_contacts(search="Joel Wembo", limit=3)
contact_id = page["data"][0]["id"]

# 4 — a two-touch sequence, built in one call
seq = ss.create_sequence(
    "SDK parity — single touch",
    description="created by the python SDK",
    steps=[{
        "subject": "{{first_name}}, a note from the SDK",
        "body_html": "<p>Sent by the python SDK.</p>",
        "delay_days": 0,
    }],
)
sid = seq["id"]
ss.add_sequence_step(sid, subject="Re: following up",
                     body_html="<p>Second touch.</p>", delay_days=2)

# 5 — activate, then enrol
ss.activate_sequence(sid)
enr = ss.enroll_in_sequence(sid, [contact_id])
print(enr["enrolled"], "enrolled;", enr["skipped"], "skipped")
for s in enr.get("skipped_details", []):
    print("  skipped", s["email"], "->", s["reason"])

# 6 — the funnel. NOTE the nesting: enrolled is top level, the counters
# are under "totals". Reading them beside enrolled returns None.
a = ss.sequence_analytics(sid)
print(a["enrolled"], "enrolled,", a["totals"]["sent"], "sent")
Output — the Python block above
authenticated as joelwembo · https://api.vxcloud.io

──── contacts ────
  full-name search -> 3 of 3
  first: [email protected]  (613f2aec-14b8-4281-9ced-19fc2c8d38a8)

──── sequences: create -> add step -> activate -> enroll -> analytics ────
  created  e16ce88a-43ab-4d7c-a2de-a8170962d705
  add step -> step_number=2 delay=2d
  steps    -> 2 hydrated (list rows carry steps_count only)
  activated
  enroll   -> 1 enrolled, [] skipped
  enrollments -> 1
      active   [email protected] at step 1
  analytics -> enrolled=1 sent=0 opened=0 replied=0
  paused (left parked, not archived)
Executed 2026-08-12 against https://api.vxcloud.io. Ids and counts are from that run; yours will differ.

Three things that will catch you