Contacts
The same person joins your waitlist, subscribes to your changelog, sends feedback and later pays you. Contacts shows them as one record.
It is not a CRM. There are no deals, pipelines, tasks or email campaigns. It is a read view over data Launch already holds, plus an optional stage and note.
How people are matched
Section titled “How people are matched”By email, after normalisation: lowercase, +alias removed, and dots ignored on Gmail. So [email protected] on the waitlist and [email protected] in Stripe are one contact. Two genuinely different addresses are two contacts; Launch does not guess.
| Source | Matched by |
|---|---|
| Waitlist signups | |
| Changelog subscribers | |
| Stripe customers (connect Stripe) | |
| Feedback | The optional email on the submission, or your user_id (see below) |
| Notifications | Your user_id |
Feedback and notifications usually carry only your own user_id. If your Stripe customers have that id in metadata, name the metadata key when connecting Stripe and Launch links user id → customer → email.
Contacts works without Stripe; you just see no payment data. Stripe customers who never used a Launch form appear with source: "stripe". A Stripe customer without an email cannot be matched and is not a contact, though they still count in revenue.
curl "https://api.nordva.dev/v1/contacts?paying=true&has_feedback=true" \ -H "Authorization: Bearer nv_live_YOUR_SECRET_KEY"| Filter | Values |
|---|---|
paying | true / false: has an active or past-due subscription |
has_feedback | true / false |
status | Waitlist status: waiting, invited, unsubscribed |
source | A utm_source or referrer hostname, or direct, referral, stripe |
stage | potential, in_talks, customer, recurring, not_a_fit, inactive |
q | Part of an email address |
limit, cursor | Cursor pagination; meta.next_cursor and meta.has_more |
Each contact has id, email, first_seen_at, source, waitlist_status, referral_count, subscribed, feedback_count, stripe_status (none, customer, trialing, active, past_due, canceled), plan, mrr_minor, currency and stage.
GET /v1/contacts/{id} adds the waitlist signup with its first-touch source, every subscription, lifetime paid per currency, the latest five feedback submissions with summaries, notifications sent and read, and the note.
Stage and note
Section titled “Stage and note”curl -X PATCH https://api.nordva.dev/v1/contacts/ct_9f2c... \ -H "Authorization: Bearer nv_live_YOUR_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "stage": "in_talks", "note": "Wants SSO before rolling out to the team." }'These are the only fields you can write. Send null to clear either. A note replaces the previous one.
| Free | Indie | Builder | |
|---|---|---|---|
| Who is listed | Waitlist people, first 100 | Everyone | Everyone |
| Stripe status, plan, MRR | — | Yes | Yes |
| Stage and note | Yes | Yes | Yes |
Deleting people
Section titled “Deleting people”A contact never outlives the person’s data. When you delete a signup in the dashboard, disconnect Stripe, or a customer is deleted in Stripe, a contact that no longer exists in any source is removed together with its note.
From an MCP client
Section titled “From an MCP client”“Which of my waitlist signups are paying now?”, “What has [email protected] asked for?”, “Mark [email protected] as in talks.” The assistant uses list_contacts, get_contact and update_contact.