Integrate Outreach candidate matching directly into your applications. Search your candidate database programmatically and get AI-powered match scores and analysis.
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.
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..."
}
Include the access token in the Authorization header for all API requests:
Authorization: Bearer YOUR_ACCESS_TOKEN
| 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. |
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
Contact us at info@taladria.com to register your application and receive your client_id and client_secret.
Never expose your client_secret in client-side code. Always make token exchanges from your server. Store refresh tokens encrypted at rest.
Search your candidate database with a job description and get AI-ranked matches.
| Header | Value | Required |
|---|---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN | Yes |
Content-Type | application/json | Yes |
{
"jobSpec": "Senior PHP Developer with Laravel experience, 5+ years, Dublin-based",
"topN": 10
}
| Field | Type | Description |
|---|---|---|
jobSpec | string | Job description or requirements to match against |
topN | integer | Number of candidates to return (1-100, default: 10) |
{
"companyId": "your-company",
"matchCount": 5,
"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...",
"bullhornId": "123456",
"bullhornUrl": "https://cls20.bullhornstaffing.com/BullhornStaffing/OpenWindow.cfm?Entity=Candidate&id=123456",
"atsType": "bullhorn"
}
]
}
| Field | Type | Description |
|---|---|---|
companyId | string | Your company identifier |
matchCount | integer | Number of matching candidates found |
matches | array | Array of candidate objects, ranked by match score |
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[].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 |
| Status | Error | Description |
|---|---|---|
| 401 | Authentication required | Missing, expired, or invalid access token |
| 400 | q (or jobSpec) is required | No job specification provided |
| 400 | topN must be 1..100 | Invalid topN value |
| 500 | Internal server error | Server-side error occurred |
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
}'
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}%")
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)}%`);
});
API requests are limited to 100 requests per minute per OAuth client. Contact us if you need higher limits.
For API support, integration assistance, or to request higher rate limits, contact us at info@taladria.com.