curl --request GET \
--url https://api.perfectreferral.com/v1/search-by-target \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.perfectreferral.com/v1/search-by-target"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.perfectreferral.com/v1/search-by-target', 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.perfectreferral.com/v1/search-by-target",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.perfectreferral.com/v1/search-by-target"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.perfectreferral.com/v1/search-by-target")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.perfectreferral.com/v1/search-by-target")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"practitionerLocations": [
{
"practitioner": {
"firstName": "<string>",
"lastName": "<string>",
"npiNumber": "<string>",
"referralScopeMatch": "very_likely_match"
},
"location": {
"address": {
"line1": "<string>",
"city": "<string>",
"state": "<string>",
"postalCode": "<string>",
"line2": "<string>"
},
"geocoding": {
"latitude": 123,
"longitude": 123
},
"staleAffiliationRisk": {
"label": "very_likely_active"
},
"bookability": {
"label": "very_likely_bookable"
}
},
"distanceMiles": 1,
"score": 50
}
],
"servedModels": {
"referralScopeMatch": "<string>",
"practitionerLocationRisk": "<string>"
},
"nextCursor": "<string>"
}{
"code": "400",
"message": "Invalid id format"
}{
"code": "401",
"message": "Unauthorized"
}{
"code": "403",
"message": "pro tier required to access this model"
}{
"code": "429",
"message": "Too Many Requests"
}{
"code": "500",
"message": "Unexpected server error"
}Find best-fit practitioners nearby
Returns nearby practitioners, ranked by how good a fit they are for a given referral target.
curl --request GET \
--url https://api.perfectreferral.com/v1/search-by-target \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.perfectreferral.com/v1/search-by-target"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.perfectreferral.com/v1/search-by-target', 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.perfectreferral.com/v1/search-by-target",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.perfectreferral.com/v1/search-by-target"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.perfectreferral.com/v1/search-by-target")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.perfectreferral.com/v1/search-by-target")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"practitionerLocations": [
{
"practitioner": {
"firstName": "<string>",
"lastName": "<string>",
"npiNumber": "<string>",
"referralScopeMatch": "very_likely_match"
},
"location": {
"address": {
"line1": "<string>",
"city": "<string>",
"state": "<string>",
"postalCode": "<string>",
"line2": "<string>"
},
"geocoding": {
"latitude": 123,
"longitude": 123
},
"staleAffiliationRisk": {
"label": "very_likely_active"
},
"bookability": {
"label": "very_likely_bookable"
}
},
"distanceMiles": 1,
"score": 50
}
],
"servedModels": {
"referralScopeMatch": "<string>",
"practitionerLocationRisk": "<string>"
},
"nextCursor": "<string>"
}{
"code": "400",
"message": "Invalid id format"
}{
"code": "401",
"message": "Unauthorized"
}{
"code": "403",
"message": "pro tier required to access this model"
}{
"code": "429",
"message": "Too Many Requests"
}{
"code": "500",
"message": "Unexpected server error"
}- Practitioner: name, NPI number, and
referralScopeMatch, our estimate of whether their billing history fits the referral target - Location: address and coordinates,
staleAffiliationRisk, our estimate of whether they are still seeing patients there, andbookability, our estimate of whether an appointment can be booked there - Distance: straight-line (not driving) miles from the coordinates you searched
- Score: from 0 to 100, how good a fit this practitioner, at this location, is for the referral you searched; higher is better
Ranking
score combines fit (referralScopeMatch), distance, and whether an appointment can be booked at the location (bookability). Ties are broken consistently, so repeating a search returns the same order.
Results are not filtered by fit: poor fits are still returned, ranked below better ones. Filter on practitioner.referralScopeMatch if you only want likely matches.
Scores are on a fixed scale, so they can be compared across searches that report the same servedModels. When servedModels has no practitionerLocationRisk, scores are computed without a bookability adjustment and locations omit both staleAffiliationRisk and bookability. Locations without a bookability label, such as those of practitioners the model does not cover, receive no adjustment.
Pagination
When more results are available, the response includesnextCursor. To get the next page, repeat the request with cursor set to that value. Stop when nextCursor is absent.
A cursor is only valid for the search that produced it: changing any other parameter returns a 400.
unlikely_match or very_unlikely_match) means a routine referral target does not fit the provider’s observed billing. It does not mean the service is outside their scope of practice or that they are unqualified; it reflects what they routinely bill, not what they are licensed or trained to do.Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your API token.
Query Parameters
The referral target to rank practitioners against, from GET /specializations/{id}/targets. Target ids change between model versions, so look them up rather than storing them.
Latitude of the point to search around, in WGS84 decimal degrees.
-90 <= x <= 90Longitude of the point to search around, in WGS84 decimal degrees.
-180 <= x <= 180How far from the coordinates to search, in straight-line miles.
1 <= x <= 25How many results to return per page.
1 <= x <= 100The nextCursor from the previous page. Send it with the same parameters as the original request.
Response
Expected response to a valid request
Results, ordered best-first by score. Empty when we have no estimate of fit for any practitioner within the radius.
Show child attributes
Show child attributes
The version of each model whose output appears in this response.
Show child attributes
Show child attributes
Opaque cursor for the next page, to be passed back as the cursor query parameter. Absent when there are no additional results.