API Documentation

database programmatically and get AI-powered match scores and analysis.

Endpoint Summary

Method Endpoint Description
POST /match-candidates Unified candidate search with optional location and must-have filtering

Authentication

The Outreach API uses OAuth 2.0 for authentication, providing secure, auditable access with per-user accountability. All API requests require a valid access token.

OAuth 2.0 Flow Overview

Step 1: Authorization Request

Redirect users to our authorization endpoint to grant access:

GET https://outreach.taladria.com/api/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://your-app.com/callback
  &response_type=code
  &state=RANDOM_STATE_STRING

Step 2: User Authorization

The user logs in with their Outreach account credentials. After approval, they are redirected back to your redirect_uri with an authorization code.

Step 3: Token Exchange

Exchange the authorization code for access and refresh tokens:

POST https://outreach.taladria.com/api/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=https://your-app.com/callback

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..."
}

Using Access Tokens

Include the access token in the Authorization header for all API requests:

Authorization: Bearer YOUR_ACCESS_TOKEN

Token Lifetimes

Token Type Lifetime Notes
access_token 1 hour Use for API requests. Refresh when expired.
refresh_token 90 days Use to obtain new access tokens. Store securely.

Refreshing Access Tokens

POST https://outreach.taladria.com/api/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=YOUR_REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
🔐 Getting OAuth Credentials

Contact us at info@taladria.com to register your application and receive your client_id and client_secret.

⚠️ Security Best Practices

Never expose your client_secret in client-side code. Always make token exchanges from your server. Store refresh tokens encrypted at rest.

Endpoints

POST https://outreach.taladria.com/api/match-candidates

Search your candidate database with a job description and get AI-ranked matches.

Request Headers

Header Value Required
Authorization Bearer YOUR_ACCESS_TOKEN Yes
Content-Type application/json Yes

Request Body

{
  "jobSpec": "Senior PHP Developer with Laravel experience, 5+ years, Dublin-based",
  "topN": 10,
  // Optional: Job title for improved search relevance and email subjects
  "jobTitle": "Senior PHP Developer",
  // Optional: Location filtering
  "jobLocation": "Dublin, Ireland",
  "radiusKm": 50,
  // Optional: Must-have requirements (ALL must be met)
  "mustHaves": "5+ years PHP, Laravel experience"
}
Field Type Required Description
jobSpec string Yes Job description or requirements to match against
topN integer No Number of candidates to return (1-100, default: 10)
jobTitle string No Job title (e.g., "Senior PHP Developer"). Improves search relevance and used in email subjects.
jobLocation string No Job location (e.g., "Dublin, Ireland") - will be geocoded automatically
jobLatitude float No Job latitude (alternative to jobLocation if already geocoded)
jobLongitude float No Job longitude (alternative to jobLocation if already geocoded)
radiusKm integer No Search radius in km when using location (1-500, default: 50)
mustHaves string No Comma-separated list of mandatory requirements. ALL must be met for a candidate to be returned.
💡 Flexible Filtering

All filtering parameters are optional. You can use location filtering, must-haves filtering, both together, or neither for a basic semantic search.

Response

{
  "companyId": "your-company",
  "matchCount": 5,
  "totalScored": 10,
  "clientRequirements": ["5+ years PHP", "Laravel experience", "Dublin-based"],
  "promptInfo": {
    "source": "company_specific",
    "versionId": "match_scoring_20240105_0920",
    "companyId": "your-company"
  },
  "matches": [
    {
      "resumeId": "abc123",
      "name": "Alex Thompson",
      "email": "alex@example.com",
      "phone": "+353 87 1234567",
      "location": "Dublin, Ireland",
      "skills": ["PHP", "Laravel", "MySQL", "Docker", "Redis"],
      "matchScore": 0.80,
      "matchReasoning": "SCORE: 80\n\nSTRENGTHS:\n**Extensive PHP Experience:** 10 years of full-stack development...\n\nCONCERNS:\n**No AI/LLM Experience:** The role requires AI integration...\n\nRECOMMENDATION: YES - Strong technical foundation makes this candidate worth interviewing.\n\nINTERVIEW_FOCUS:\n**AI Learning Aptitude:** Assess willingness to learn AI/LLM technologies...",
      "meets_all_must_haves": true,
      "must_haves_identified": ["5+ years PHP", "Laravel experience", "Dublin-based"],
      "bullhornId": "123456",
      "bullhornUrl": "https://cls20.bullhornstaffing.com/BullhornStaffing/OpenWindow.cfm?Entity=Candidate&id=123456",
      "atsType": "bullhorn"
    }
  ]
}

Response Fields

Field Type Description
companyId string Your company identifier
matchCount integer Number of qualified candidates (meeting all must-haves)
totalScored integer Total candidates scored by AI before must-have filtering
clientRequirements array Combined essential requirements identified from both JD and client input
promptInfo object Metadata about the AI prompt used (source, version, etc.) for transparency
matches array Array of candidate objects, ranked by match score (only those meeting all must-haves)
matches[].resumeId string Unique candidate identifier
matches[].name string Candidate's full name
matches[].email string Candidate's email address
matches[].phone string Candidate's phone number
matches[].location string Candidate's location
matches[].skills array List of skills extracted from CV
matches[].matchScore float AI match score (0.0 to 1.0)
matches[].matchReasoning string Detailed AI analysis with strengths, concerns, recommendation
matches[].meets_all_must_haves boolean True if candidate meets ALL identified must-have requirements
matches[].must_haves_identified array List of must-have requirements AI identified from JD
matches[].bullhornId string Bullhorn candidate ID (if synced from Bullhorn ATS)
matches[].bullhornUrl string Direct URL to open candidate in Bullhorn
matches[].atsType string ATS type (e.g., "bullhorn") - empty if not from ATS

Error Responses

Status Error Description
401 Authentication required Missing, expired, or invalid access token
400 q (or jobSpec) is required No job specification provided
400 jobLocation or jobLatitude/jobLongitude required No location provided for location-search
400 radiusKm must be 1..500 Invalid radius value
400 topN must be 1..100 Invalid topN value
500 Internal server error Server-side error occurred

Code Examples

cURL

curl -X POST \
  https://outreach.taladria.com/api/match-candidates \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -d '{
    "jobSpec": "Senior PHP Developer with Laravel, 5+ years experience",
    "topN": 5
  }'

Python

import requests

response = requests.post(
    "https://outreach.taladria.com/api/match-candidates",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_ACCESS_TOKEN"
    },
    json={
        "jobSpec": "Senior PHP Developer with Laravel, 5+ years experience",
        "topN": 5
    }
)

data = response.json()
for candidate in data["matches"]:
    print(f"{candidate['name']}: {candidate['matchScore']*100:.0f}%")

JavaScript / Node.js

const response = await fetch(
  "https://outreach.taladria.com/api/match-candidates",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer YOUR_ACCESS_TOKEN"
    },
    body: JSON.stringify({
      jobSpec: "Senior PHP Developer with Laravel, 5+ years experience",
      topN: 5
    })
  }
);

const data = await response.json();
data.matches.forEach(candidate => {
  console.log(`${candidate.name}: ${(candidate.matchScore * 100).toFixed(0)}%`);
});

Location + Must-Haves Example (Python)

import requests

# Combined location and must-haves filtering (unified endpoint)
response = requests.post(
    "https://outreach.taladria.com/api/match-candidates",
    headers={
        "Content-Type": "application/json",
        "Authorization": "Bearer YOUR_ACCESS_TOKEN"
    },
    json={
        "jobSpec": "Senior PHP Developer with Laravel",
        "jobLocation": "Dublin, Ireland",
        "radiusKm": 50,
        "mustHaves": "5+ years PHP, Laravel experience",
        "topN": 10
    }
)

data = response.json()
print(f"Found {data['matchCount']} candidates within {data.get('radiusKm', 'N/A')}km")
for candidate in data["matches"]:
    distance = candidate.get('distanceKm', 'N/A')
    print(f"{candidate['name']}: {candidate['matchScore']*100:.0f}% - {distance}km away")
⚠️ Rate Limits

API requests are limited to 100 requests per minute per OAuth client. Contact us if you need higher limits.

Need Help?

For API support, integration assistance, or to request higher rate limits, contact us at info@taladria.com.