curl --request POST \
--url https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"delivery": "email",
"locale": "<string>",
"org_name": "<string>",
"redirect_base_url": "<string>"
}
'import requests
url = "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite"
payload = {
"delivery": "email",
"locale": "<string>",
"org_name": "<string>",
"redirect_base_url": "<string>"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
delivery: 'email',
locale: '<string>',
org_name: '<string>',
redirect_base_url: '<string>'
})
};
fetch('https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'delivery' => 'email',
'locale' => '<string>',
'org_name' => '<string>',
'redirect_base_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite"
payload := strings.NewReader("{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"verify_url": "<string>",
"invite_expires_at": "2023-11-07T05:31:56Z"
}{
"invited": true,
"invite_expires_at": "2023-11-07T05:31:56Z",
"delivery_state": "sent"
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}Send a verification invite
Accepts an application API key or a dashboard session. delivery: email preserves the established email flow. delivery: none is application-principal-only and returns a verify URL directly with a single-use invite credential whose TTL defaults to and cannot exceed 15 minutes; the URL is never logged. The recipient is ALWAYS the LINKED PROFILE’s email resolved from the Minerva profiles service AT SEND TIME for email delivery; the request no longer carries to_email. Direct delivery performs no profile-email lookup. An empty profile email -> 422 idv_profile_email_missing (add an email to the profile first); a profile-service lookup failure -> 503 idv_profile_lookup_unavailable. Creates or refreshes an invite credential (default lifetime 72 hours), builds the verify URL on the public verification host, and sends the email. The invite is persisted AFTER the email resolves but BEFORE delivery, so a 502 leaves a usable invite for a re-invite retry. The recipient email is PII: never persisted or logged; the invite code appears only in the emailed URL fragment.
curl --request POST \
--url https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"delivery": "email",
"locale": "<string>",
"org_name": "<string>",
"redirect_base_url": "<string>"
}
'import requests
url = "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite"
payload = {
"delivery": "email",
"locale": "<string>",
"org_name": "<string>",
"redirect_base_url": "<string>"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
delivery: 'email',
locale: '<string>',
org_name: '<string>',
redirect_base_url: '<string>'
})
};
fetch('https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'delivery' => 'email',
'locale' => '<string>',
'org_name' => '<string>',
'redirect_base_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite"
payload := strings.NewReader("{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gominerva.com/idv/v1/sessions/{sessionId}/invite")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"delivery\": \"email\",\n \"locale\": \"<string>\",\n \"org_name\": \"<string>\",\n \"redirect_base_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"verify_url": "<string>",
"invite_expires_at": "2023-11-07T05:31:56Z"
}{
"invited": true,
"invite_expires_at": "2023-11-07T05:31:56Z",
"delivery_state": "sent"
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}{
"error": {
"code": "idv_session_not_found",
"message": "<string>"
}
}Authorizations
Authorization: Api-Key <application_api_key> (legacy X-Api-Key also accepted).
Headers
Email delivery only (delivery:none ignores it). Bounded opaque key (1-160 chars from [A-Za-z0-9._:-]). When absent or invalid the server generates a fresh key. A replay under a key that already owns a delivery reports that delivery's durable state: 202 sent once the provider has accepted the message, otherwise 502 invite_delivery_failed. A DIFFERENT key may replace the intent only once it has stopped owning a live send (delivered, or a terminally failed delivery); the message is then emailed again under the new key (the resend path). While a send is in flight, including an ambiguous provider outcome held as provider_retry, a different key is refused with 409 idv_state_conflict; a same-key replay never sends a second email.
1 - 160Path Parameters
Body
The recipient email is NOT accepted: it is always the linked profile's email resolved at send time for email delivery. Every field is optional.
email sends through the verification email service with the configured invite lifetime. none is application-principal-only and returns a single-use verify URL without looking up or sending to an email. Its lifetime defaults to 15 minutes and cannot exceed 15 minutes.
email, none BCP-47-like tag echoed into the email template (e.g. en-US).
Organization name shown in the invite email (overrides the theme company name).
Optional absolute HTTPS public base URL override for an intentional white-label verify link; falls back to the standard public verification URL when absent. HTTP is accepted only for loopback addresses in a positively local environment. Userinfo, query, and fragment components are forbidden.