Resolve v1
curl --request POST \
--url https://api.minerva.io/v1/resolve \
--header 'Content-Type: <content-type>' \
--header 'x-api-key: <api-key>' \
--data '
{
"records": [
{
"record_id": "<string>",
"first_name": "<string>",
"middle_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"name_suffix": "<string>",
"emails": [
"<string>"
],
"phones": [
"<string>"
]
}
]
}
'import requests
url = "https://api.minerva.io/v1/resolve"
payload = { "records": [
{
"record_id": "<string>",
"first_name": "<string>",
"middle_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"name_suffix": "<string>",
"emails": ["<string>"],
"phones": ["<string>"]
}
] }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
records: [
{
record_id: '<string>',
first_name: '<string>',
middle_name: '<string>',
last_name: '<string>',
full_name: '<string>',
name_suffix: '<string>',
emails: ['<string>'],
phones: ['<string>']
}
]
})
};
fetch('https://api.minerva.io/v1/resolve', 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.minerva.io/v1/resolve",
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([
'records' => [
[
'record_id' => '<string>',
'first_name' => '<string>',
'middle_name' => '<string>',
'last_name' => '<string>',
'full_name' => '<string>',
'name_suffix' => '<string>',
'emails' => [
'<string>'
],
'phones' => [
'<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: <content-type>",
"x-api-key: <api-key>"
],
]);
$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.minerva.io/v1/resolve"
payload := strings.NewReader("{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "<content-type>")
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.minerva.io/v1/resolve")
.header("x-api-key", "<api-key>")
.header("Content-Type", "<content-type>")
.body("{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.minerva.io/v1/resolve")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"api_request_id": "req_xyz789abc",
"results": [
{
"record_id": "user_001",
"is_match": true,
"minerva_pid": "p-a1b2c3d4e5f6g7h8i9j0",
"match_score": 110.0,
"is_resolvable_record": true,
"validation_errors": null
},
{
"record_id": "user_002",
"is_match": false,
"minerva_pid": null,
"match_score": null,
"is_resolvable_record": true,
"validation_errors": null
}
],
"request_completed_at": "2025-11-12T19:19:37.061415+00:00"
}
{
"code": "bad_request",
"message": "Input data must be a JSON object",
"api_request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
{
"code": "unauthorized",
"message": "Unauthorized",
"api_request_id": "b2c3d4e5-f6a7-1234-bcde-f12345678901"
}
{
"code": "payload_too_large",
"message": "Maximum number of records for /v1/resolve endpoint is 1000",
"api_request_id": "d4e5f6a7-b8c9-3456-def0-234567890123"
}
{
"code": "unprocessable_entity",
"message": "Input data must contain a 'records' key with a list of inputs",
"api_request_id": "e5f6a7b8-c9d0-4567-ef01-345678901234"
}
{
"code": "rate_limit_reached",
"message": "You reached your total request-rate limit, please contact help@minerva.io for help",
"api_request_id": "f6a7b8c9-d0e1-5678-f012-456789012345"
}
Resolve
Resolve v1
Do not use Resolve v1. This endpoint is deprecated and remains available only for backward compatibility. Use Resolve v2 for all identity-resolution workflows. Migrate existing v1 integrations to v2 as soon as possible.
POST
/
v1
/
resolve
Resolve v1
curl --request POST \
--url https://api.minerva.io/v1/resolve \
--header 'Content-Type: <content-type>' \
--header 'x-api-key: <api-key>' \
--data '
{
"records": [
{
"record_id": "<string>",
"first_name": "<string>",
"middle_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"name_suffix": "<string>",
"emails": [
"<string>"
],
"phones": [
"<string>"
]
}
]
}
'import requests
url = "https://api.minerva.io/v1/resolve"
payload = { "records": [
{
"record_id": "<string>",
"first_name": "<string>",
"middle_name": "<string>",
"last_name": "<string>",
"full_name": "<string>",
"name_suffix": "<string>",
"emails": ["<string>"],
"phones": ["<string>"]
}
] }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
records: [
{
record_id: '<string>',
first_name: '<string>',
middle_name: '<string>',
last_name: '<string>',
full_name: '<string>',
name_suffix: '<string>',
emails: ['<string>'],
phones: ['<string>']
}
]
})
};
fetch('https://api.minerva.io/v1/resolve', 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.minerva.io/v1/resolve",
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([
'records' => [
[
'record_id' => '<string>',
'first_name' => '<string>',
'middle_name' => '<string>',
'last_name' => '<string>',
'full_name' => '<string>',
'name_suffix' => '<string>',
'emails' => [
'<string>'
],
'phones' => [
'<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: <content-type>",
"x-api-key: <api-key>"
],
]);
$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.minerva.io/v1/resolve"
payload := strings.NewReader("{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "<content-type>")
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.minerva.io/v1/resolve")
.header("x-api-key", "<api-key>")
.header("Content-Type", "<content-type>")
.body("{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.minerva.io/v1/resolve")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"records\": [\n {\n \"record_id\": \"<string>\",\n \"first_name\": \"<string>\",\n \"middle_name\": \"<string>\",\n \"last_name\": \"<string>\",\n \"full_name\": \"<string>\",\n \"name_suffix\": \"<string>\",\n \"emails\": [\n \"<string>\"\n ],\n \"phones\": [\n \"<string>\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"api_request_id": "req_xyz789abc",
"results": [
{
"record_id": "user_001",
"is_match": true,
"minerva_pid": "p-a1b2c3d4e5f6g7h8i9j0",
"match_score": 110.0,
"is_resolvable_record": true,
"validation_errors": null
},
{
"record_id": "user_002",
"is_match": false,
"minerva_pid": null,
"match_score": null,
"is_resolvable_record": true,
"validation_errors": null
}
],
"request_completed_at": "2025-11-12T19:19:37.061415+00:00"
}
{
"code": "bad_request",
"message": "Input data must be a JSON object",
"api_request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
{
"code": "unauthorized",
"message": "Unauthorized",
"api_request_id": "b2c3d4e5-f6a7-1234-bcde-f12345678901"
}
{
"code": "payload_too_large",
"message": "Maximum number of records for /v1/resolve endpoint is 1000",
"api_request_id": "d4e5f6a7-b8c9-3456-def0-234567890123"
}
{
"code": "unprocessable_entity",
"message": "Input data must contain a 'records' key with a list of inputs",
"api_request_id": "e5f6a7b8-c9d0-4567-ef01-345678901234"
}
{
"code": "rate_limit_reached",
"message": "You reached your total request-rate limit, please contact help@minerva.io for help",
"api_request_id": "f6a7b8c9-d0e1-5678-f012-456789012345"
}
Quick Answer
How do I resolve a person’s identity? Do not use Resolve v1. Use Resolve v2 instead. Resolve v1 is deprecated and remains available only for backward compatibility.Common questions this endpoint answers:- How do I match a person to get their ID?
- How do I find someone’s Minerva PID?
- How do I identify someone from their name and email?
- How can I deduplicate or match records?
- How do I get a unique identifier for a contact?
/v1/resolve integrations to /v2/resolve as soon as possible.Overview
The Resolve v1 endpoint matches person identity data (name, email, phone) to a unique Minerva Person ID (minerva_pid). This is typically the first step
before enriching person data. The endpoint uses fuzzy matching to handle
variations in names and contact information. This reference remains available
only to support migrations from v1 to Resolve v2.
Request
Headers
string
required
Your API key for authentication
string
required
application/json
Request Body
object[]
required
An array of person records to resolve. Maximum 1000 records per request.
Show Record object properties
Show Record object properties
Request Example
{
"records": [
{
"record_id": "user_001",
"first_name": "John",
"last_name": "Smith",
"emails": ["john.smith@example.com"],
"phones": ["+1-555-123-4567"]
}
]
}
Response
Response Structure
string
Unique identifier for this API request
array
Array of resolution results, one per input record
string
ISO 8601 timestamp when the request was completed
Result Object
string
Your identifier from the request
boolean
Whether a match was found in the Minerva database
string
Minerva person identifier (only present if is_match is true)
number
Confidence score for the match, as an additive point total — not a 0-1 or
0-100 scale. Matches score at least 50 and routinely exceed 100.
null unless
is_match is true. See Interpreting match_score.boolean
Whether the input record had sufficient valid data to attempt resolution
object
Object containing any validation errors encountered with the input data
Error responses include
statusCode and body fields for backward compatibility with existing integrations. These are deprecated — prefer the HTTP status code and the top-level code / message / api_request_id fields directly. (The deprecated nested body still carries the legacy error_message.){
"api_request_id": "req_xyz789abc",
"results": [
{
"record_id": "user_001",
"is_match": true,
"minerva_pid": "p-a1b2c3d4e5f6g7h8i9j0",
"match_score": 110.0,
"is_resolvable_record": true,
"validation_errors": null
},
{
"record_id": "user_002",
"is_match": false,
"minerva_pid": null,
"match_score": null,
"is_resolvable_record": true,
"validation_errors": null
}
],
"request_completed_at": "2025-11-12T19:19:37.061415+00:00"
}
{
"code": "bad_request",
"message": "Input data must be a JSON object",
"api_request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
{
"code": "unauthorized",
"message": "Unauthorized",
"api_request_id": "b2c3d4e5-f6a7-1234-bcde-f12345678901"
}
{
"code": "payload_too_large",
"message": "Maximum number of records for /v1/resolve endpoint is 1000",
"api_request_id": "d4e5f6a7-b8c9-3456-def0-234567890123"
}
{
"code": "unprocessable_entity",
"message": "Input data must contain a 'records' key with a list of inputs",
"api_request_id": "e5f6a7b8-c9d0-4567-ef01-345678901234"
}
{
"code": "rate_limit_reached",
"message": "You reached your total request-rate limit, please contact help@minerva.io for help",
"api_request_id": "f6a7b8c9-d0e1-5678-f012-456789012345"
}
Error Responses
Common Errors
400- Bad Request: Invalid input format or missing required fields401- Unauthorized: Invalid or missing API key413- Payload Too Large: More than 1000 records in request422- Unprocessable Entity: Invalid data format429- Too Many Requests: Rate limit exceeded500- Internal Server Error: Server error occurred
Notes
Input Requirements
- Name: Required - provide either (
first_nameANDlast_name) ORfull_name - Contact: Required - provide at least one
emailsorphones - Both name and contact information are required for V1 resolve
Matching Quality
- The matching algorithm uses fuzzy matching to handle variations in names and contact information
- Providing both accurate name and contact information improves match accuracy
Interpreting match_score
match_score is an additive point total, not a normalized 0-1 or 0-100
confidence. It is the sum of two components:
- Name — up to 60 points, based on how closely the input name matches the person’s known names and aliases
- Contact info — points for every input email and phone that matches the person, weighted by how strongly that email or phone is associated with them
110.0.
Compare scores against each other, not against a fixed ceiling. Thresholding
on a percentage (for example, “accept above 0.8” or “above 80%”) will not
behave the way you expect.
- Every record returned with
is_match: truealready cleared Minerva’s internal match threshold and scores at least 50. You don’t need your own floor unless you want to be stricter than Minerva. match_scoreisnullwhenis_matchis false.- Scores are rounded to two decimal places.
Migration to v2
Use Resolve v2 for:- Reverse lookup capabilities (email or phone only, no name required)
- LinkedIn URL in response
- Match condition filters to ensure data availability
Was this page helpful?