apna job vacancy data API
apna is the Android job-search client candidates in India use to browse vacancies, one-click apply, and track recruiter replies. The data API behind those screens starts at /v1/jobs/feed for the city feed and /v1/jobs/detail/{jobId} for a single vacancy card, then layers on the signed-in profile at /v1/profile/me and the applied-jobs pipeline at /v1/jobs/applied.
apna is India's job-search and vacancy app for blue-collar, grey-collar and early-career roles: candidates browse a city-filtered feed, open a vacancy card, one-click apply, and track hiring status while recruiters reach them by phone. Behind those screens the app talks to a JSON API over HTTPS. Signed-in calls attach an Authorization token header plus session and client-version headers; the token pair comes from the phone OTP login. The surface below covers the employee job feed, vacancy detail, applied-jobs pipeline, the aggregated candidate profile, OTP login, and one-click apply.
Screenshots
API surface
Employee job feed
GET
/v1/jobs/feedopendataReturns the paginated city/area job feed used by the home Jobs tab: title, salary band, category, WFH/part-time flags, openings and employer logo.
Auth: Authorization: Token <accessToken> from OTP login; Client-Session and Client-Version headers.
- count
- defaultSalary
- jobs
- id
- title
- minSalary
- maxSalary
- jobCategory
- jobCategoryName
- locationName
- locationType
- experienceLevel
- education
- openings
- isWfh
- isPartTime
- expired
- promoted
- shift
- workDaysDesc
- workHoursDesc
- organization
- name
- logoUrl
- externalId
- lastUpdated
- myJobsCount
- otherJobsCount
- currentPageNumber
- isLastPage
- jobsCountMessage
- callBackCount
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/feed?area_id=14094&page_vertical=0&page=1&categoryId=42&minSalary=15000&isWfh=false HTTP/1.1 Authorization: Token <accessToken> Client-Session: <session> Client-Version: 2026.16.09 Accept: application/json{ "count": 1284, "defaultSalary": 18000, "jobs": [{ "id": "86750", "title": "Delivery Executive", "minSalary": "15000", "maxSalary": "22000", "jobCategory": "delivery", "jobCategoryName": "Delivery", "locationName": "Bengaluru", "locationType": "city", "experienceLevel": "0-1", "education": "10th pass", "openings": 12, "isWfh": false, "isPartTime": false, "expired": false, "promoted": true, "shift": "day", "workDaysDesc": "6 days a week", "workHoursDesc": "8 hours", "organization": {"name": "Example Logistics", "logoUrl": "https://cdn.example.com/org/logo.png", "externalId": "org-4412"}, "lastUpdated": "2026-09-23T08:12:00Z" }], "myJobsCount": 18, "otherJobsCount": 1266, "currentPageNumber": 1, "isLastPage": false, "jobsCountMessage": "1,284 jobs near you", "callBackCount": 3 }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the app's home Jobs tab and its city-filtered vacancy listfield set mirrors the job cards shown in the candidate feed
Vacancy detail
GET
/v1/jobs/detail/{jobId}opendataHydrates the vacancy-detail screen: full jobDescription, salary band, HR number, skillTags, working hours, and candidateEligibility used before apply.
Auth: Authorization: Token <accessToken>; Client-Session and Client-Version headers.
- job
- id
- title
- jobDescription
- minSalary
- maxSalary
- salaryDetail
- hrNumber
- locationName
- experienceLevel
- education
- gender
- openings
- isWfh
- isPartTime
- isNearbyLocation
- expired
- skillTags
- organization
- application_status
- consultancyName
- isCreatorConsultant
- isCreatorInternal
- isHrVideoVisible
- workingHour
- candidateEligibility
- assessment
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/detail/86750 HTTP/1.1 Authorization: Token <accessToken> Client-Session: <session> Client-Version: 2026.16.09 Accept: application/json{ "job": { "id": "86750", "title": "Delivery Executive", "jobDescription": "Pick up and drop parcels across Bengaluru. Two-wheeler required.", "minSalary": "15000", "maxSalary": "22000", "salaryDetail": "Plus fuel incentive", "hrNumber": "+91-98XXXXXX21", "locationName": "Bengaluru", "experienceLevel": "0-1", "education": "10th pass", "gender": "any", "openings": 12, "isWfh": false, "isPartTime": false, "isNearbyLocation": true, "expired": false, "skillTags": ["driving", "navigation"], "organization": {"name": "Example Logistics", "logoUrl": "https://cdn.example.com/org/logo.png", "externalId": "org-4412"}, "application_status": null }, "consultancyName": null, "isCreatorConsultant": false, "isCreatorInternal": true, "isNearbyLocation": true, "isHrVideoVisible": false, "workingHour": {"start": "09:00", "end": "18:00"}, "candidateEligibility": {"eligible": true, "reason": null}, "assessment": {"required": false} }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the vacancy-detail screen a candidate opens before applying
Applied jobs pipeline
GET
/v1/jobs/appliedopendataLists the candidate's applied vacancies with pipeline fields (hiringState, connectionStatus, appliedAt, numberShareStatus) for the My Jobs / track-application screen.
Auth: Authorization: Token <accessToken>; Client-Session and Client-Version headers.
- count
- nextPageUrl
- previousPageUrl
- results
- id
- title
- minSalary
- maxSalary
- locationName
- organization
- application_status
- userApplication
- status
- originalStatus
- hiringState
- connectionStatus
- communicationStatus
- appliedAt
- leadCreatedAt
- lastUpdated
- numberShareStatus
- userMatched
- softRejected
- searchedJob
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/applied?col_id=my_jobs&page=1&page_size=10 HTTP/1.1 Authorization: Token <accessToken> Client-Session: <session> Client-Version: 2026.16.09 Accept: application/json{ "count": 18, "nextPageUrl": "/v1/jobs/applied?col_id=my_jobs&page=2&page_size=10", "previousPageUrl": null, "results": [{ "id": "86750", "title": "Delivery Executive", "minSalary": "15000", "maxSalary": "22000", "locationName": "Bengaluru", "organization": {"name": "Example Logistics", "externalId": "org-4412"}, "application_status": "applied", "userApplication": { "id": 902114, "status": "applied", "originalStatus": "applied", "hiringState": "shortlisted", "connectionStatus": "number_shared", "communicationStatus": "whatsapp_sent", "appliedAt": "2026-09-20T11:04:00Z", "leadCreatedAt": "2026-09-20T11:04:12Z", "lastUpdated": "2026-09-21T09:30:00Z", "numberShareStatus": "shared", "userMatched": true, "softRejected": false } }], "searchedJob": null }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the My Jobs / track-application screen
Aggregated candidate profile
GET
/v1/profile/meosintReturns the signed-in candidate's aggregated profile used by the Profile tab: fullName, salary, experience, skills, education, resume URL, verified email and city/area.
Auth: Authorization: Token <accessToken>; Client-Session and Client-Version headers.
- userId
- enrichedProfile
- id
- fullName
- gender
- profileUrl
- currentSalary
- currentSalaryV2
- totalYearsOfExperience
- totalMonthsOfExperience
- noticePeriod
- isExperienced
- isVerifiedProfile
- views
- dateOfBirth
- experienceType
- contactInfo
- emailStatus
- city
- area
- skills
- educations
- experiences
- resume
- format
- url
- pageCount
- uploadedAt
- enrichedPrefs
- jobRoles
- jobTypes
- languageId
- oldProfile
- phoneNumber
- community
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/profile/me HTTP/1.1 Authorization: Token <accessToken> Client-Session: <session> Client-Version: 2026.16.09 Accept: application/json{ "userId": "1851645", "enrichedProfile": { "id": "1851645", "fullName": "Ravi Kumar", "gender": "male", "profileUrl": "https://profiles.example.com/1851645", "currentSalary": 18000, "currentSalaryV2": 18000, "totalYearsOfExperience": 2.5, "totalMonthsOfExperience": 30, "noticePeriod": 15, "isExperienced": true, "isVerifiedProfile": true, "views": 142, "dateOfBirth": "1999-04-12", "experienceType": "experienced", "contactInfo": {"email": "[email protected]", "emailStatus": "verified"}, "city": {"id": 1, "name": "Bengaluru"}, "area": {"id": 14094, "name": "Whitefield"}, "skills": [{"id": 11, "name": "driving"}], "educations": [{"degree": "12th pass", "institute": "Govt PU College"}], "experiences": [{"title": "Delivery Executive", "company": "Example Logistics"}], "resume": {"isValid": true, "format": "pdf", "url": "https://cdn.example.com/resume/1851645.pdf", "pageCount": 1, "uploadedAt": "2026-08-01T10:00:00Z"} }, "enrichedPrefs": { "userId": "1851645", "languageId": "hi", "jobRoles": [{"id": 73, "name": "Delivery Executive"}], "jobTypes": [{"id": 4, "name": "Full time"}] }, "oldProfile": {"id": 1851645, "fullName": "Ravi Kumar", "phoneNumber": "9876543210"}, "community": {"claps": 12, "friends": 34} }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the Profile tab's aggregated candidate view
OTP login
POST
/v1/auth/otp/verifyosintExchanges a phone OTP for the accessToken/refreshToken pair and userId that every subsequent job, profile and apply call attaches as Authorization: Token.
Auth: Unauthenticated. Subsequent calls use Authorization: Token <accessToken> from this response.
- phone_number
- otp
- requestId
- channel
- accessToken
- refreshToken
- userId
- isProfileComplete
Illustrative example reconstructed from the app's interface — not a live capture.
POST /v1/auth/otp/verify HTTP/1.1 Content-Type: application/json Client-Version: 2026.16.09 Accept: application/json { "phone_number": "9876543210", "otp": "482193", "requestId": "req-9f3a", "channel": "sms" }{ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refreshToken": "rt_8c1e2b...", "userId": 1851645, "isProfileComplete": true }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the phone-number sign-in flow
One-click / easy apply jobs
GET
/v1/jobs/quick-apply/{userId}opendataReturns vacancies the signed-in candidate can one-click apply to (userEligible, allowSuperApply) for the Easy Apply / Super Apply flow.
Auth: Authorization: Token <accessToken>; Client-Session and Client-Version headers.
- jobs
- id
- title
- minSalary
- maxSalary
- locationName
- allowSuperApply
- isSuperApplyJob
- organization
- userEligible
- userInUnleash
- message
- title
- subtitle
Illustrative example reconstructed from the app's interface — not a live capture.
GET /v1/jobs/quick-apply/1851645?areaId=14094 HTTP/1.1 Authorization: Token <accessToken> Client-Session: <session> Client-Version: 2026.16.09 Accept: application/json{ "jobs": [{ "id": "86750", "title": "Delivery Executive", "minSalary": "15000", "maxSalary": "22000", "locationName": "Bengaluru", "allowSuperApply": true, "isSuperApplyJob": true, "organization": {"name": "Example Logistics", "externalId": "org-4412"} }], "userEligible": true, "userInUnleash": true, "message": { "title": "Apply in one tap", "subtitle": "We will share your apna profile with the recruiter" } }Derived from the app's interface; endpoint details are illustrative, not a live capture.
reconstructed from the Easy Apply / Super Apply flow
Data categories
- job listings
- vacancy details
- applications
- candidate profiles
- auth sessions
Where teams use this data
Hyperlocal vacancy ingestion
A workforce marketplace can poll /v1/jobs/feed by area_id, categoryId and minSalary and store title, salary band, locationName, openings and organization.name for a live India vacancy catalog.
Candidate CRM enrichment
HRIS tools can call /v1/profile/me to attach fullName, currentSalary, totalYearsOfExperience, skills, educations, resume.url and verified email onto an existing applicant record.
Application pipeline sync
ATS bots can page /v1/jobs/applied and map userApplication.hiringState, connectionStatus, appliedAt and numberShareStatus into interview-stage dashboards.
One-click apply eligibility
Staffing partners can read /v1/jobs/quick-apply/{userId} to see which vacancies the candidate is userEligible to Super Apply, then open /v1/jobs/detail/{jobId} for jobDescription and candidateEligibility before submitting.
Frequently asked questions
What job fields does the apna feed return?
The job feed returns title, minSalary, maxSalary, jobCategoryName, locationName, experienceLevel, openings, isWfh, isPartTime and the employer organization name and logoUrl. Vacancy detail adds jobDescription, hrNumber, skillTags and candidateEligibility.
How does a candidate authenticate?
The app posts a phone OTP to /v1/auth/otp/verify and stores accessToken, refreshToken, userId and isProfileComplete. Later calls send Authorization: Token <accessToken> plus Client-Session and Client-Version headers.
Can I read a candidate's profile and applications?
Yes. /v1/profile/me returns fullName, currentSalary, skills, educations, resume URL and verified email. /v1/jobs/applied returns each application's hiringState, connectionStatus and appliedAt.
Where does one-click apply live?
/v1/jobs/quick-apply/{userId} lists vacancies the signed-in user is userEligible to Super Apply, including allowSuperApply on each job card.
Topics
- apna job api
- apna vacancy feed
- job feed endpoint
- candidate profile api
- applied jobs hiringState
- apna otp login
- one click apply jobs
- India job search data
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.