{"openapi":"3.1.0","info":{"title":"NVM API","version":"1.0.0","description":"NVM answers every click on an email’s links: a person goes on to the destination at once, a security scanner, crawler or link preview never does. This API reads what NVM decided, click by click, campaign by campaign and recipient by recipient, and signs links for tools that cannot hold a secret."},"servers":[{"url":"/"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Your API key: nvm_live_..."}},"schemas":{"Click":{"type":"object","properties":{"object":{"type":"string","enum":["click"]},"id":{"type":"string","example":"f47ac10b-58cc-4372-a567-0e02b2c3d479"},"at":{"type":"string"},"campaign":{"type":"string"},"recipient":{"type":"string"},"slot":{"type":"number","description":"The link’s place in the email, from 1."},"url":{"type":["string","null"],"description":"The destination."},"sent_at":{"type":["string","null"]},"age_seconds":{"type":["number","null"],"description":"Seconds from the send to the click."},"verdict":{"type":"string","enum":["human","machine","unverified","pending"],"description":"human: a person reached the destination. machine: stopped, failed the check, or found afterwards to be a scanner. unverified: the check page went out and no proof came back within ten minutes. pending: that check is still open."},"label":{"type":"string","enum":["human_verified","human_likely","unknown","bot","pending"],"description":"The verdict in four labels. human_verified: the browser proved itself on the check page, or the click came from a mobile carrier or a webmail page. human_likely: a person by the request alone."},"released":{"type":"boolean","description":"Whether the reader went on to the destination."},"action":{"type":"string","enum":["pass","prove","challenge","stop"],"description":"What NVM did at the click. pass: sent the reader on at once. prove: an invisible browser check. challenge: a check that asks for one tap. stop: a blank page."},"basis":{"type":"array","items":{"type":"string"},"description":"The signs the verdict rests on, heaviest first.","example":["net:home","hdr:browser","tls:browser","time:over-1h"]},"decided_at":{"type":["string","null"]},"mailbox":{"type":["string","null"],"description":"Who hosts the recipient’s mailbox, from the address the link was signed for: gmail, yahoo, microsoft, apple, isp, business, education, government, relay, other or unknown."},"network":{"$ref":"#/components/schemas/Network"},"place":{"$ref":"#/components/schemas/Place"},"browser":{"type":"object","properties":{"name":{"type":["string","null"]},"os":{"type":["string","null"]},"mobile":{"type":["boolean","null"]}},"required":["name","os","mobile"]},"events":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"kind":{"type":"string"},"action":{"type":"string"},"outcome":{"type":"string"},"signs":{"type":"array","items":{"type":"string"}},"machine_weight":{"type":"number"},"person_weight":{"type":"number"},"decision_us":{"type":["number","null"]}},"required":["at","kind","action","outcome","signs","machine_weight","person_weight","decision_us"]},"description":"Only on GET /v1/clicks/{id}: every request of the click, its own and its check page’s."},"updated_at":{"type":"string"}},"required":["object","id","at","campaign","recipient","slot","url","sent_at","age_seconds","verdict","label","released","action","basis","decided_at","mailbox","network","place","browser","updated_at"]},"Network":{"type":"object","properties":{"asn":{"type":["number","null"],"example":7922},"name":{"type":["string","null"],"example":"Comcast"},"kind":{"type":["string","null"],"description":"home; mobile; cloud; security: an email or web security company; proxy: a company’s web gateway; relay: a privacy relay, a VPN or a CDN; or other."}},"required":["asn","name","kind"]},"Place":{"type":"object","properties":{"country":{"type":["string","null"],"example":"US"},"region":{"type":["string","null"],"example":"SC"},"city":{"type":["string","null"],"example":"Greenville"}},"required":["country","region","city"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["invalid_request_error","authentication_error","rate_limit_error","not_found_error","api_error"]},"code":{"type":"string"},"message":{"type":"string"},"param":{"type":["string","null"]}},"required":["type","code","message"]}},"required":["error"]},"Open":{"type":"object","properties":{"object":{"type":"string","enum":["open"]},"id":{"type":"string"},"at":{"type":"string"},"campaign":{"type":"string"},"recipient":{"type":"string"},"class":{"type":"string","enum":["apple-privacy","gmail-proxy","yahoo-proxy","outlook","scanner","person","unknown"],"description":"apple-privacy: Apple Mail Privacy Protection, which loads every image whether anyone reads or not. gmail-proxy and yahoo-proxy: the mail service fetching for a reader who opened the email. outlook: Outlook fetching for its reader. scanner: a security scanner or other machine. person: a mail app or browser on a home or mobile network."},"human":{"type":"boolean","description":"Whether the open is a person reading."},"signs":{"type":"array","items":{"type":"string"}},"mailbox":{"type":["string","null"]},"network":{"$ref":"#/components/schemas/Network"},"place":{"$ref":"#/components/schemas/Place"},"browser":{"type":"object","properties":{"name":{"type":["string","null"]},"os":{"type":["string","null"]}},"required":["name","os"]}},"required":["object","id","at","campaign","recipient","class","human","signs","mailbox","network","place","browser"]},"CampaignSummary":{"type":"object","properties":{"object":{"type":"string","enum":["campaign"]},"id":{"type":"string"},"clicks":{"$ref":"#/components/schemas/Counts"},"first_click_at":{"type":"string"},"last_click_at":{"type":"string"}},"required":["object","id","clicks","first_click_at","last_click_at"]},"Counts":{"type":"object","properties":{"total":{"type":"number"},"human":{"type":"number"},"machine":{"type":"number"},"unverified":{"type":"number"},"pending":{"type":"number"},"released":{"type":"number","description":"Clicks whose reader went on to the destination."},"leaked":{"type":"number","description":"Released clicks found afterwards to be a machine, by their email’s trap or a burst of links."},"unique_humans":{"type":"number","description":"Recipients with at least one human click."},"bot_share":{"type":["number","null"],"description":"Machine and unverified clicks over every settled click, 0 to 1."}},"required":["total","human","machine","unverified","pending","released","leaked","unique_humans","bot_share"]},"Campaign":{"type":"object","properties":{"object":{"type":"string","enum":["campaign"]},"id":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"clicks":{"allOf":[{"$ref":"#/components/schemas/Counts"},{"type":"object","properties":{"unique_clickers":{"type":"number"}},"required":["unique_clickers"]}]},"first_click_at":{"type":["string","null"]},"first_human_click_at":{"type":["string","null"]},"last_click_at":{"type":["string","null"]},"links":{"type":"array","items":{"type":"object","properties":{"slot":{"type":"number"},"url":{"type":["string","null"],"description":"The slot’s most common destination."},"distinct_urls":{"type":"number"},"clicks":{"$ref":"#/components/schemas/Counts"}},"required":["slot","url","distinct_urls","clicks"]}},"mailboxes":{"type":"array","items":{"type":"object","properties":{"mailbox":{"type":"string"},"clicks":{"$ref":"#/components/schemas/Counts"}},"required":["mailbox","clicks"]}},"opens":{"type":"object","properties":{"total":{"type":"number"},"human":{"type":"number"},"unique_human_openers":{"type":"number"},"classes":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string"},"opens":{"type":"number"},"recipients":{"type":"number"}},"required":["class","opens","recipients"]}}},"required":["total","human","unique_human_openers","classes"]}},"required":["object","id","from","to","clicks","first_click_at","first_human_click_at","last_click_at","links","mailboxes","opens"]},"Recipient":{"type":"object","properties":{"object":{"type":"string","enum":["recipient"]},"id":{"type":"string"},"active":{"type":"boolean","description":"A human click or open in the last 30 days."},"last_human_click_at":{"type":["string","null"]},"last_human_open_at":{"type":["string","null"]},"human_clicks":{"type":"number"},"machine_clicks":{"type":"number"},"human_opens":{"type":"number"},"machine_opens":{"type":"number"},"updated_at":{"type":"string"}},"required":["object","id","active","last_human_click_at","last_human_open_at","human_clicks","machine_clicks","human_opens","machine_opens","updated_at"]},"Verdict":{"type":"object","properties":{"object":{"type":"string","enum":["verdict"]},"id":{"type":"string","description":"NVM’s id for the event."},"ref":{"type":["string","null"],"description":"Your id for the event, as you sent it."},"type":{"type":"string","enum":["click","open"]},"human":{"type":"boolean","description":"NVM’s single answer: is this a person? For an uncertain verdict, true when the machine signs weigh under 25."},"verdict":{"type":"string","enum":["human","machine","uncertain"]},"confidence":{"type":"string","enum":["certain","high","medium","low"],"description":"certain: a sign no browser shows, such as a robot’s name, a HEAD request or Apple’s privacy fetch. low: the request alone cannot tell."},"class":{"type":["string","null"],"description":"For an open: apple-privacy, gmail-proxy, yahoo-proxy, outlook, scanner, person or unknown."},"signs":{"type":"array","items":{"type":"string"},"example":["net:home","time:over-1h"]},"machine_weight":{"type":"number"},"person_weight":{"type":"number"},"network":{"type":"object","properties":{"asn":{"type":["number","null"]},"name":{"type":["string","null"]},"kind":{"type":"string"}},"required":["asn","name","kind"]},"browser":{"type":"object","properties":{"name":{"type":"string"},"os":{"type":"string"},"mobile":{"type":"boolean"}},"required":["name","os","mobile"]},"age_seconds":{"type":["number","null"],"description":"Seconds from delivery, or from the send, to the event."}},"required":["object","id","ref","type","human","verdict","confidence","class","signs","machine_weight","person_weight","network","browser","age_seconds"]},"ActivityInput":{"type":"object","properties":{"id":{"type":"string","maxLength":128,"description":"Your id for the event, returned as ref."},"type":{"type":"string","enum":["click","open"],"description":"click: a request to a tracked link. open: a request for a tracking pixel."},"at":{"type":"string","format":"date-time","description":"When it happened. Default: now."},"ip":{"type":"string","maxLength":45,"description":"The reader’s IP address, as your server or your email platform saw it. NVM finds its network.","example":"73.162.20.14"},"user_agent":{"type":"string","maxLength":2048},"headers":{"type":"object","additionalProperties":{"type":"string","maxLength":4096},"description":"Every request header you have, by name. NVM judges them against the browser the User-Agent names, and ignores what a CDN or load balancer adds. Leave it out when you have none: a missing header weighs nothing."},"method":{"type":"string","maxLength":10,"description":"The HTTP method. Default GET. A HEAD or OPTIONS request is always a machine’s."},"asn":{"type":"integer","minimum":0,"maximum":4294967295,"description":"The network, if your edge reads it: Cloudflare’s request.cf.asn or Vercel’s x-vercel-ip-as-number."},"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO country code, if your edge reads it."},"region":{"type":"string","maxLength":10},"city":{"type":"string","maxLength":100},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"ja4":{"type":"string","maxLength":64,"description":"The JA4 fingerprint of the TLS handshake, if your edge reads it."},"sent_at":{"type":"string","format":"date-time","description":"When the email was handed to the email platform."},"delivered_at":{"type":"string","format":"date-time","description":"When the mailbox accepted the email. Scanners fetch at delivery, so this is the better clock."},"campaign":{"type":"string","maxLength":256,"description":"Your id for the email’s campaign. With recipient, lets NVM see one email’s links opened together."},"recipient":{"type":"string","maxLength":256},"link":{"type":"integer","minimum":0,"maximum":32767,"description":"The link’s place in the email."},"url":{"type":"string","maxLength":2000,"description":"The link’s destination."},"email":{"type":"string","maxLength":254,"description":"The recipient’s address. NVM uses only its domain, to name who hosts the mailbox, and stores neither."},"mailbox":{"type":"string","enum":["unknown","gmail","yahoo","microsoft","apple","isp","business","education","government","relay","other"],"description":"Who hosts the mailbox, if you know it and give no email."},"any_country":{"type":"boolean","description":"No weight on a reader outside the United States."},"early":{"type":"boolean","description":"No weight on activity soon after the send: for transactional email."}},"required":["type"]},"SigningKey":{"type":"object","properties":{"object":{"type":"string","enum":["signing_key"]},"id":{"type":"number"},"name":{"type":"string"},"created_at":{"type":"string"},"revoked_at":{"type":["string","null"]},"live":{"type":"boolean"}},"required":["object","id","name","created_at","revoked_at","live"]}},"parameters":{}},"paths":{"/v1/clicks":{"get":{"tags":["Clicks"],"summary":"List clicks","description":"Every click on your links with its verdict, newest first. A click’s verdict settles within a minute, or eleven minutes when its reader got the browser check; sort=updated with updated_since returns every click NVM wrote since your last sync.","parameters":[{"schema":{"type":"string","description":"Your campaign id: only its clicks."},"required":false,"description":"Your campaign id: only its clicks.","name":"campaign","in":"query"},{"schema":{"type":"string","description":"Your recipient id: only their clicks."},"required":false,"description":"Your recipient id: only their clicks.","name":"recipient","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":255,"description":"Only clicks on the link in this place of the email."},"required":false,"description":"Only clicks on the link in this place of the email.","name":"slot","in":"query"},{"schema":{"type":"string","description":"Comma-separated verdicts: human, machine, unverified, pending."},"required":false,"description":"Comma-separated verdicts: human, machine, unverified, pending.","name":"verdict","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"true: only clicks whose reader went on to the destination. false: only the others."},"required":false,"description":"true: only clicks whose reader went on to the destination. false: only the others.","name":"released","in":"query"},{"schema":{"type":"string","description":"Clicks at or after this time: a date, YYYY-MM-DD, from midnight in New York, or an ISO date-time. Default: 30 days ago, unless campaign or recipient is given."},"required":false,"description":"Clicks at or after this time: a date, YYYY-MM-DD, from midnight in New York, or an ISO date-time. Default: 30 days ago, unless campaign or recipient is given.","name":"since","in":"query"},{"schema":{"type":"string","description":"Clicks before this time, which is not included."},"required":false,"description":"Clicks before this time, which is not included.","name":"until","in":"query"},{"schema":{"type":"string","description":"ISO date-time. With sort=updated: every click NVM wrote after it, the basis of incremental sync."},"required":false,"description":"ISO date-time. With sort=updated: every click NVM wrote after it, the basis of incremental sync.","name":"updated_since","in":"query"},{"schema":{"type":"string","enum":["recent","updated"],"description":"recent, the default: newest first. updated: by the time NVM last wrote the click, oldest first, at least 30 seconds behind."},"required":false,"description":"recent, the default: newest first. updated: by the time NVM last wrote the click, oldest first, at least 30 seconds behind.","name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":1000,"description":"Default 100."},"required":false,"description":"Default 100.","name":"limit","in":"query"},{"schema":{"type":"string","description":"The next_cursor of the page before."},"required":false,"description":"The next_cursor of the page before.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of clicks.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Click"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/clicks/{id}":{"get":{"tags":["Clicks"],"summary":"Retrieve a click and why NVM judged it so","parameters":[{"schema":{"type":"string","example":"f47ac10b-58cc-4372-a567-0e02b2c3d479"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The click, with every request it made.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Click"}}}},"404":{"description":"No such click.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/opens":{"get":{"tags":["Opens"],"summary":"List opens","description":"Every request for your emails’ pixels, newest first, each named by who fetched it.","parameters":[{"schema":{"type":"string","description":"Your campaign id: only its opens."},"required":false,"description":"Your campaign id: only its opens.","name":"campaign","in":"query"},{"schema":{"type":"string","description":"Your recipient id: only their opens."},"required":false,"description":"Your recipient id: only their opens.","name":"recipient","in":"query"},{"schema":{"type":"string","description":"Comma-separated classes: apple-privacy, gmail-proxy, yahoo-proxy, outlook, scanner, person, unknown."},"required":false,"description":"Comma-separated classes: apple-privacy, gmail-proxy, yahoo-proxy, outlook, scanner, person, unknown.","name":"class","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"true: only opens by a person reading. false: only the others."},"required":false,"description":"true: only opens by a person reading. false: only the others.","name":"human","in":"query"},{"schema":{"type":"string","description":"A date or an ISO date-time. Default: 30 days ago, unless campaign or recipient is given."},"required":false,"description":"A date or an ISO date-time. Default: 30 days ago, unless campaign or recipient is given.","name":"since","in":"query"},{"schema":{"type":"string","description":"Opens before this time, which is not included."},"required":false,"description":"Opens before this time, which is not included.","name":"until","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":1000,"description":"Default 100."},"required":false,"description":"Default 100.","name":"limit","in":"query"},{"schema":{"type":"string","description":"The next_cursor of the page before."},"required":false,"description":"The next_cursor of the page before.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of opens.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Open"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/campaigns":{"get":{"tags":["Campaigns"],"summary":"List campaigns with clicks","description":"Campaigns with a click since a time, the latest first, each with its counts.","parameters":[{"schema":{"type":"string","description":"A date or an ISO date-time. Default: 7 days ago."},"required":false,"description":"A date or an ISO date-time. Default: 7 days ago.","name":"since","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Default 50."},"required":false,"description":"Default 50.","name":"limit","in":"query"},{"schema":{"type":"string","description":"The next_cursor of the page before."},"required":false,"description":"The next_cursor of the page before.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of campaigns.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CampaignSummary"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/campaigns/{id}":{"get":{"tags":["Campaigns"],"summary":"A campaign’s clicks and opens","description":"Counts for the whole campaign, for each link by its slot, and for each mailbox class, and its opens by class. unique_humans of a link is its payable clicks: one for each recipient a person clicked for.","parameters":[{"schema":{"type":"string","example":"greenville-2026-10-14"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"A date or an ISO date-time. Default: 60 days ago."},"required":false,"description":"A date or an ISO date-time. Default: 60 days ago.","name":"since","in":"query"},{"schema":{"type":"string","description":"Counts up to this time, which is not included. Default: now."},"required":false,"description":"Counts up to this time, which is not included. Default: now.","name":"until","in":"query"}],"responses":{"200":{"description":"The campaign.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Campaign"}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No click or open of this campaign in the window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recipients":{"get":{"tags":["Recipients"],"summary":"Sync recipients’ engagement","description":"Every recipient whose human or machine clicks and opens changed after updated_since, in the order of the change. A click counts here eleven minutes after it happens, when nothing can change its verdict; the list runs at least 30 seconds behind.","parameters":[{"schema":{"type":"string","description":"ISO date-time. Default: every recipient."},"required":false,"description":"ISO date-time. Default: every recipient.","name":"updated_since","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":1000,"description":"Default 1000."},"required":false,"description":"Default 1000.","name":"limit","in":"query"},{"schema":{"type":"string","description":"The next_cursor of the page before."},"required":false,"description":"The next_cursor of the page before.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A page of recipients.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Recipient"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}},"required":["object","data","has_more","next_cursor"]}}}},"400":{"description":"A parameter is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/recipients/{id}":{"get":{"tags":["Recipients"],"summary":"A recipient’s engagement","description":"The recipient’s last human click and open, and counts of human and machine clicks and opens. Machine clicks and opens never make a recipient active.","parameters":[{"schema":{"type":"string","example":"sub_8d1f20"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The recipient.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Recipient"}}}},"404":{"description":"No click or open of this recipient yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/classify":{"post":{"tags":["Activity"],"summary":"Is this open or click a person?","description":"Send each open and click your own pixel, redirect or email platform saw, one or up to 1,000 at a time; NVM answers for each, in order, in about a millisecond. Give what you have: an IP address and a User-Agent are enough for most events, and headers, the network, the TLS fingerprint and the delivery time make the answer surer. Events of one email, with the same campaign and recipient, in one batch are judged together: four links opened in three seconds are a scanner.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/ActivityInput"},"minItems":1,"maxItems":1000}},"required":["events"]}}}},"responses":{"200":{"description":"A verdict for each event, in the order sent.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Verdict"}}},"required":["object","data"]}}}},"400":{"description":"An event is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/links":{"post":{"tags":["Links"],"summary":"Sign links, pixels and traps","description":"NVM signs with your newest live signing key. For whole sends, sign in your own code with the SDK, with no request per link; this endpoint is for tools that cannot hold a secret.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"links":{"type":"array","items":{"type":"object","properties":{"campaign":{"type":"string","minLength":1,"description":"Your id for the campaign or issue, at most 64 bytes.","example":"greenville-2026-10-14"},"recipient":{"type":"string","minLength":1,"description":"Your id for the recipient, at most 64 bytes. Never the address: links travel with forwarded emails.","example":"sub_8d1f20"},"email":{"type":"string","maxLength":254,"description":"The recipient’s address. NVM uses only its domain, to name who hosts the mailbox; it never enters the link."},"sent_at":{"type":"string","format":"date-time","description":"When the email is handed to the email platform. Default: now."},"strict":{"type":"boolean","description":"Every click proves itself in the browser, even one the request alone shows to be a person. For links sold by the click."},"any_country":{"type":"boolean","description":"No weight on a reader outside the United States."},"early":{"type":"boolean","description":"No weight on a click soon after the send. For transactional email."},"type":{"type":"string","enum":["click","pixel","trap"],"description":"click, the default: a link to url. pixel: the open pixel. trap: the hidden link that only scanners request."},"url":{"type":"string","maxLength":2000,"description":"The destination of a click: http or https.","example":"https://example.com/story"},"slot":{"type":"integer","minimum":1,"maximum":255,"description":"The link’s place in the email. Default 1."}},"required":["campaign","recipient"]},"minItems":1,"maxItems":1000}},"required":["links"]}}}},"responses":{"200":{"description":"The links, in the order asked.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["link"]},"type":{"type":"string"},"url":{"type":"string"}},"required":["object","type","url"]}}},"required":["object","data"]}}}},"400":{"description":"A link is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No live signing key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/wrap":{"post":{"tags":["Links"],"summary":"Wrap every link of an email","description":"Wraps every http and https link of the HTML in order from slot 1, leaving any link marked data-nvm=\"off\" as it is, and adds the open pixel before </body>. With trap: true it also adds a hidden trap link; it is off by default because, by Gmail’s sender guidelines, hidden content can send mail to spam. The SDK’s wrap function does the same in your code.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"type":"string","minLength":1,"description":"Your id for the campaign or issue, at most 64 bytes.","example":"greenville-2026-10-14"},"recipient":{"type":"string","minLength":1,"description":"Your id for the recipient, at most 64 bytes. Never the address: links travel with forwarded emails.","example":"sub_8d1f20"},"email":{"type":"string","maxLength":254,"description":"The recipient’s address. NVM uses only its domain, to name who hosts the mailbox; it never enters the link."},"sent_at":{"type":"string","format":"date-time","description":"When the email is handed to the email platform. Default: now."},"strict":{"type":"boolean","description":"Every click proves itself in the browser, even one the request alone shows to be a person. For links sold by the click."},"any_country":{"type":"boolean","description":"No weight on a reader outside the United States."},"early":{"type":"boolean","description":"No weight on a click soon after the send. For transactional email."},"html":{"type":"string","minLength":1,"maxLength":2000000},"trap":{"type":"boolean"},"pixel":{"type":"boolean"}},"required":["campaign","recipient","html"]}}}},"responses":{"200":{"description":"The wrapped HTML and the number of links wrapped.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"html":{"type":"string"},"links":{"type":"number"}},"required":["object","html","links"]}}}},"409":{"description":"No live signing key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/signing-keys":{"get":{"tags":["Links"],"summary":"Your signing keys","description":"The keys your links are signed with, never their secrets. A link signed with a revoked key answers 410 Gone.","responses":{"200":{"description":"Every signing key of your account.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/SigningKey"}}},"required":["object","data"]}}}}}}}},"webhooks":{}}