Indeed Job Search data API
Indeed Job Search exposes a graph-style job API — illustrated below as /v1/jobs/recommendations and /v1/jobs/cards — plus REST-style calls for application status (/v1/applications/status), interviews (/v1/interviews/list), unread counts, session-to-token exchange (/v1/auth/token) and keyword typeahead (/v1/suggest/keywords).
Indeed Job Search (package com.indeed.android.jobsearch, version 296.1.0) is Indeed's Android client for job search, applications, interviews and employer messaging. Behind the home feed, My Jobs, sign-in and inbox screens the app calls a graph-style job API (recommended jobs, job-card hydration, session init, account profile, employer conversations, recent searches, resume tags) plus REST-style endpoints for application status, interview lists, unread message counts, session-to-token exchange, keyword autocomplete and new-job counts. Anonymous calls send an app API-key header with country and locale headers; signed-in calls add an OAuth Bearer access token.
Screenshots
API surface
Find relevant jobs (widget)
POST
/v1/jobs/recommendationsopendataPowers the Android home-screen widget: up to five relevant jobs with matchReason, title, sourceEmployerName, overallRating, compensation.formattedText and viewJobRedirectClickUrl.
Auth: App API-key header plus country, locale, client and tracking headers. Optional OAuth Bearer access token after sign-in.
- findRelevantJobs
- trackingKey
- matchReason
- title
- sourceEmployerName
- employer
- key
- overallRating
- location
- formatted
- compensation
- formattedText
- indeedApply
- scopes
- dateOnIndeed
- description
- viewJobRedirectClickUrl
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/jobs/recommendations HTTP/1.1 Content-Type: application/json X-App-Key: <app-api-key> X-Country: US X-Locale: en_US X-Client: android-widget X-Tracking-Key: <tk> { "limit": 5, "context": "homeWidget" }{ "trackingKey": "1abcdefghijklmn", "results": [{ "matchReason": {"type": "RECENT_QUERY", "query": "product manager", "location": "Austin, TX"}, "job": { "title": "Staff Product Manager", "sourceEmployerName": "Example Corp", "employer": {"key": "example-corp", "overallRating": {"value": 4.1}}, "location": {"formatted": {"short": "Austin, TX"}}, "compensation": {"key": "USD_140K_180K", "formattedText": "$140,000 - $180,000 a year"}, "indeedApply": {"scopes": ["RESUME"]}, "dateOnIndeed": "2026-09-24T12:00:00Z", "description": {"text": "Own the job-seeker home feed."} }, "viewJobRedirectClickUrl": "https://example.com/viewjob?jk=abc123" }] }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the home-screen widget's job-refresh flow.Observed in the widget payload that carries up to five recommended jobs with match reasons.
Hydrate job cards
POST
/v1/jobs/cardsopendataHydrates SERP and conversation job cards from jobKeys: title, formatted location, employer logos, overallRating, compensation.formattedText and attributes.
Auth: App API-key header plus country, locale and tracking headers. Optional OAuth Bearer access token.
- jobData
- key
- url
- title
- location
- formatted
- short
- long
- sourceEmployerName
- squareLogoUrls
- url64
- url128
- overallRating
- compensation
- formattedText
- attributes
- label
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/jobs/cards HTTP/1.1 Content-Type: application/json X-App-Key: <app-api-key> X-Country: US X-Locale: en_US X-Tracking-Key: <tk> { "jobKeys": ["abc123def456"] }{ "results": [{ "job": { "key": "abc123def456", "url": "https://example.com/viewjob?jk=abc123def456", "title": "Staff Product Manager", "location": {"formatted": {"short": "Austin, TX", "long": "Austin, TX 78701"}}, "sourceEmployerName": "Example Corp", "employer": { "squareLogoUrls": {"url64": "https://example.com/s/logo64.png", "url128": "https://example.com/s/logo128.png"}, "overallRating": {"value": 4.1} }, "compensation": {"formattedText": "$140,000 - $180,000 a year"}, "attributes": [{"key": "jobtype", "label": "Full-time"}] } }] }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the search-results and conversation job-card hydration flow.
Jobseeker mobile app init
POST
/v1/session/initopendataBootstraps the jobseeker session: cookie tracking key (ctk), service URLs, experiment buckets, IP country, terms-of-service banner and force-upgrade flags.
Auth: App API-key header plus country and locale headers. Optional OAuth Bearer access token.
- jobseekerMobileAppInit
- ctk
- services
- name
- url
- proctorResult
- deviceId
- matrixVersion
- ipCountry
- ipLookupCountry
- attributionParametersPayload
- affiliateKey
- showBlockingTOSBanner
- showForceUpgradeModal
- tosModalContent
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/session/init HTTP/1.1 Content-Type: application/json X-App-Key: <app-api-key> X-Country: US X-Locale: en_US { "platform": "ANDROID", "appVersion": "296.1.0" }{ "ctk": "1ctkexample", "services": [{"name": "jobgraph", "url": "https://example.com/v1"}], "proctorResult": {"deviceId": "dev-9f2a", "matrixVersion": "2026.09.1"}, "ipCountry": "US", "ipLookupCountry": "US", "attributionParametersPayload": {"affiliateKey": "", "host": "www.example.com", "keywords": "product manager"}, "showBlockingTOSBanner": false, "showForceUpgradeModal": false, "tosModalContent": {"version": "2026-01"} }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the app launch sequence that bootstraps the jobseeker session.
Current Passport account
POST
/v1/account/profileosintLoads the signed-in Passport identity used by the Me tab — firstName, lastName, emailAddress, isVerified, accountId — plus inbox unread counters.
Auth: OAuth Bearer access token from the session-token exchange, plus app API-key, country and locale headers.
- currentUser
- PassportAccount
- firstName
- lastName
- emailAddress
- isVerified
- accountId
- isConfirmed
- isSignedIn
- creationDate
- globalUnreadEventCount
- unreadConversationCount
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/account/profile HTTP/1.1 Content-Type: application/json Authorization: Bearer <access_token> X-App-Key: <app-api-key> X-Country: US X-Locale: en_US { "include": ["accountProfile", "unreadCounts"] }{ "currentUser": { "account": { "type": "PassportAccount", "accountProfile": { "accountName": {"firstName": "Alex", "lastName": "Rivera"}, "email": {"emailAddress": "[email protected]", "isVerified": true} }, "accountId": "acct-1001", "emailAddress": "[email protected]", "isConfirmed": true, "isSignedIn": true, "creationDate": "2019-04-12T08:11:00Z" } }, "globalUnreadEventCount": 3, "unreadConversationCount": 2 }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the Me tab's signed-in account loading flow.
Find employer conversations
POST
/v1/messages/conversationsosintPages the signed-in jobseeker inbox: conversation id, unreadCount, employer participants, attached job, lastEvent.messagePreview and moderationStatus.
Auth: OAuth Bearer access token from the session-token exchange, plus app API-key, country, locale and tracking headers.
- findConversations
- conversations
- id
- unreadCount
- participants
- role
- accountKey
- participantName
- job
- key
- title
- lastEvent
- messagePreview
- locks
- reasonCode
- moderationStatus
- pageInfo
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/messages/conversations HTTP/1.1 Content-Type: application/json Authorization: Bearer <access_token> X-App-Key: <app-api-key> X-Country: US X-Locale: en_US X-Tracking-Key: <tk> { "conversationFilter": {"excludedLabels": ["ARCHIVE", "SPAM"]}, "first": 20 }{ "conversations": [{ "id": "Y29udjoxMjM", "userReadsInfo": {"unreadCount": 1}, "participants": [{"role": "EMPLOYER", "accountKey": "emp-441", "participantName": "Example Corp Recruiter"}], "job": {"key": "abc123def456", "title": "Staff Product Manager"}, "lastEvent": {"type": "MESSAGE", "messagePreview": "Are you free Thursday?"}, "locks": {"reasonCode": null}, "moderationStatus": "NONE" }], "pageInfo": {"endCursor": "cursor-20", "hasNextPage": true} }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the employer-message inbox paging flow.
Recent job searches
POST
/v1/search/recentopendataReturns the signed-in jobseeker's recent search criteria (query, location) used to seed the home feed and widget.
Auth: OAuth Bearer access token from the session-token exchange, plus app API-key, country and locale headers.
- currentJobSeekerPortrait
- rawActivities
- recentJobSearches
- uid
- timestamp
- criteria
- query
- location
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/search/recent HTTP/1.1 Content-Type: application/json Authorization: Bearer <access_token> X-App-Key: <app-api-key> X-Country: US X-Locale: en_US {}{ "recentJobSearches": [{ "uid": "rjs-7788", "timestamp": "2026-09-26T18:04:00Z", "criteria": {"query": "product manager", "location": "Austin, TX"} }] }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the home feed's recent-search seeding behavior.
Resume tags on jobseeker profile
POST
/v1/profile/resume-tagsosintReads resume id and tags from the signed-in jobSeekerProfile used when applying and matching jobs.
Auth: OAuth Bearer access token from the session-token exchange, plus app API-key, country and locale headers.
- jobSeekerProfile
- profile
- resume
- id
- tags
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/profile/resume-tags HTTP/1.1 Content-Type: application/json Authorization: Bearer <access_token> X-App-Key: <app-api-key> X-Country: US X-Locale: en_US {}{ "jobSeekerProfile": { "profile": { "resume": { "id": "resume-9", "tags": ["product-management", "b2b-saas"] } } } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the apply flow's resume handling.
Application-status jobs (My Jobs)
GET
/v1/applications/statusopendataLists applied and visited jobs for the My Jobs tab: jobKey, company.name, pipeline statuses, applyTime, encryptedIaAppId and applicationStatus.
Auth: Session cookie or OAuth Bearer access token. Query params type, applyUpdateStartTime, tk (tracking key) and from.
- success
- appStatusJobs
- appTk
- jobTitle
- jobKey
- jobUrl
- jobExpired
- jobFraudulent
- withdrawn
- location
- company
- name
- candidateStatus
- selfReportedStatus
- employerJobStatus
- userJobStatus
- applyTime
- indeedApplyable
- encryptedIaAppId
- encryptedAdvCandId
- applicationStatus
- applicationStatusAction
- applicationStatusTimestamp
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/applications/status?type=APPLIED&applyUpdateStartTime=0&tk=<tk>&from=myjobs HTTP/1.1 Authorization: Bearer <access_token> Accept: application/json{ "success": true, "body": { "appStatusJobs": [{ "appTk": "1apptk", "jobTitle": "Staff Product Manager", "jobKey": "abc123def456", "jobUrl": "https://example.com/viewjob?jk=abc123def456", "jobExpired": false, "jobReported": false, "jobFraudulent": false, "withdrawn": false, "location": "Austin, TX", "company": {"name": "Example Corp"}, "statuses": { "candidateStatus": {"status": "APPLIED", "timestamp": 1727049600000}, "selfReportedStatus": {"status": "WAITING", "timestamp": 1727049600000}, "employerJobStatus": {"status": "ACTIVE", "timestamp": 1727049600000}, "userJobStatus": {"status": "APPLIED"} }, "applyTime": 1727049600000, "indeedApplyable": true, "hasIaAppId": true, "hasApplicationPreview": true, "hasInterviewNowAccess": false, "normalizedJobTitle": "product manager", "employerEstimatedResponseDays": 7, "encryptedIaAppId": "ia-enc-1", "encryptedAdvCandId": "cand-enc-1", "applicationStatus": "UNDER_REVIEW", "applicationStatusAction": "WAIT", "applicationStatusTimestamp": 1727136000000, "companyApplyUrl": null }] } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the My Jobs application-list refresh.
List interviews
GET
/v1/interviews/listopendataLoads interview invitations for My Jobs: formatType, status, durationInMinutes, invitationNote, jobDetails and timeSlots.
Auth: Session cookie or OAuth Bearer access token. Query params statuses, formats, start, tk and from.
- id
- externalInterviewId
- formatType
- status
- durationInMinutes
- interviewGTS
- outcome
- invitationNote
- availabilityBasedScheduling
- jobDetails
- title
- company
- jobKey
- jobUrl
- location
- fraudulent
- timeSlots
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/interviews/list?statuses=INVITED,SCHEDULED&formats=VIDEO,PHONE&start=0&tk=<tk>&from=myjobs HTTP/1.1 Authorization: Bearer <access_token> Accept: application/json{ "success": true, "body": { "interviews": [{ "id": "int-441", "externalInterviewId": "ext-882", "formatType": "VIDEO", "status": "SCHEDULED", "durationInMinutes": "30", "interviewGTS": true, "outcome": null, "invitationNote": "Looking forward to chatting.", "availabilityBasedScheduling": true, "jobDetails": { "title": "Staff Product Manager", "company": "Example Corp", "jobKey": "abc123def456", "jobUrl": "https://example.com/viewjob?jk=abc123def456", "location": "Austin, TX", "fraudulent": "false", "reportedByUser": "false" }, "timeSlots": [{"start": "2026-09-30T16:00:00Z", "end": "2026-09-30T16:30:00Z"}] }] } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the interview invitations screen in My Jobs.
Unread messages summary
GET
/v1/messages/unread-summaryosintBadge counts for the Messages tab: totalUnreadConversationCount and totalUnreadMessageCount.
Auth: Session cookie or OAuth Bearer access token. A fixed client query parameter identifies the Android app.
- data
- totalUnreadConversationCount
- totalUnreadMessageCount
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/messages/unread-summary?client=android-app HTTP/1.1 Authorization: Bearer <access_token> Accept: application/json{ "data": { "totalUnreadConversationCount": 2, "totalUnreadMessageCount": 5 } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the Messages tab badge update.
Convert session cookies to OAuth token
POST
/v1/auth/tokenosintExchanges sign-in session cookies for an OAuth access_token / expires_in / scope / token_type used as Bearer auth on the app's graph and jobs services.
Auth: Session cookies on the request (including the refresh-token cookie). Form fields client_id and scope. Subsequent calls send Authorization: Bearer access_token.
- client_id
- scope
- access_token
- expires_in
- token_type
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/auth/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Cookie: refresh_token=<refresh> client_id=android-app&scope=openid%20profile%20email{ "access_token": "eyJhbGciOi...", "expires_in": 3600, "scope": "openid profile email", "token_type": "Bearer" }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the sign-in session upgrade flow.
Keyword autocomplete (what)
GET
/v1/suggest/keywordsopendataTypeahead for the What search box: query plus country/language/ctk return suggestion strings used on the search results page.
Auth: Unauthenticated. Query params query, ctk, country, language, count; optional session identifiers.
- query
- ctk
- country
- language
- count
- formatted
- suggestion
- formattedSuggestion
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/suggest/keywords?query=product%20man&ctk=<ctk>&country=US&language=en&count=8&formatted=1 HTTP/1.1 Accept: application/json[ { "suggestion": "product manager", "formattedSuggestion": "<b>product man</b>ager" }, { "suggestion": "product management intern", "formattedSuggestion": "<b>product man</b>agement intern" } ]Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the search box typeahead behavior.
New jobs count for a saved search
GET
/v1/jobs/new-countopendataReturns how many new postings match a saved keyword/location pair since a timestamp — drives the new-jobs badge.
Auth: Optional sign-in session. Query params hl, q (keyword), l (location) and since (epoch).
- status
- body
- key
- newCount
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/new-count?hl=en&q=product%20manager&l=Austin%2C%20TX&since=1727049600000 HTTP/1.1 Accept: application/json{ "status": "ok", "body": { "key": "product manager|Austin, TX", "newCount": 14 } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
Mapped from the saved-search new-jobs badge.
Data categories
- job listings
- applications
- interviews
- identity
- messaging
- search history
- resumes
Where teams use this data
Talent-pipeline reconciliation
An ATS nightly-syncs My Jobs applicationStatus, encryptedIaAppId and interview formatType/status so recruiters see the same pipeline a candidate sees in Indeed.
Job-market pulse from public cards
A labour-market dashboard hydrates getJobsData cards (title, compensation.formattedText, overallRating, location.formatted) without storing candidate PII.
Inbox SLA for employer replies
A jobseeker CRM watches FindConversations unreadCount plus messaging/jobseekers/v2/summary totals to page when an employer thread goes stale.
Identity match at apply time
A background-check vendor binds Passport firstName/lastName/emailAddress/accountId from initGraph to the resume id returned by GetResumeTags before submitting Indeed Apply.
Frequently asked questions
Where do Indeed job cards come from?
The app posts to a graph-style job API — illustrated as /v1/jobs/recommendations for the home widget and /v1/jobs/cards for result cards — returning title, employer name, compensation text and overall rating.
How does Indeed Job Search authenticate?
Calls send an app API-key header with country and locale headers. After sign-in the app exchanges its session at /v1/auth/token for an OAuth access token sent as Bearer auth.
What identity fields does the signed-in account expose?
The account profile call returns first name, last name, email address, verification state and account id, plus inbox unread counters.
Which calls power My Jobs?
GET /v1/applications/status lists applied jobs with each application's pipeline status; GET /v1/interviews/list lists interview invitations with format, time slots and job details.
Topics
- Indeed Job Search API
- Indeed job recommendations API
- Indeed application status API
- Indeed session token exchange
- Indeed interviews API
- Indeed autocomplete suggestions
Need this app's data API integrated?
We deliver scoped integrations for any named app — from USD 500 with source-code handoff, or hosted access billed per call. Tell us the data you need.