Unified.to
All articles

How to Build a Candidate Portal Showing Real-Time Interview Stages Using Unified's ATS API


February 25, 2026

Candidates increasingly expect visibility into their application progress.

If you're building:

  • A candidate portal
  • A recruiting automation layer
  • A branded apply experience
  • A talent CRM with applicant login
  • A hiring marketplace

You may need to display:

  • Current application stage
  • Upcoming interviews
  • Interview outcomes
  • Rejection or hire status

This guide walks through how to build a candidate-facing portal that reflects real-time ATS data using Unified's ATS API.

The focus is:

  • Current stage visibility
  • Interview scheduling visibility
  • Real-time updates
  • Safe synchronization

Unified exposes the current state of applications and interviews. It does not reconstruct stage history or enforce stage ordering.

The Mental Model

A candidate portal should reflect three layers:

  1. Application status (AtsApplication.status)
  2. Interview schedule (AtsInterview)
  3. Stage vocabulary (AtsStatus)

All data should be synced into your own database and updated via webhooks or incremental refresh.

The ATS remains the source of truth. Your portal becomes a read-only projection layer.

Step 1: Retrieve the Candidate's Application

You need the application associated with the candidate and job.

Endpoint

GET /ats/{connection_id}/application

Filter by candidate:

const applications = await sdk.ats.listAtsApplications({
  connectionId,
  candidate_id: candidateId,
  limit: 50,
  offset: 0,
  sort: 'updated_at',
  order: 'asc',
});

From each AtsApplication, extract:

  • id
  • status
  • original_status
  • applied_at
  • rejected_at
  • hired_at

Current Stage Display

The primary stage to show in a portal is:

application.status

Optionally display:

application.original_status

This allows you to show the recruiter-defined stage label exactly as configured inside the ATS.

Important: Unified exposes the current status only. It does not provide a stage transition history timeline.

Step 2: Retrieve Stage Vocabulary

To render consistent labels and descriptions, retrieve available statuses:

GET /ats/{connection_id}/applicationstatus

Node SDK

const statuses = await sdk.ats.listAtsApplicationstatuses({
  connectionId,
  limit: 50,
  offset: 0,
});

AtsStatus includes:

  • status
  • original_status
  • description

Use this to:

  • Display friendly stage names
  • Show stage descriptions in your UI
  • Handle unknown raw statuses safely

Note: The API does not define stage ordering or progression logic. If you want ordered stages, you must define ordering in your own application layer.

Step 3: Retrieve Interviews

If the ATS integration supports interviews, you can surface scheduling data.

Interview visibility depends on provider support.

Endpoint

GET /ats/{connection_id}/interview

Filter by application:

const interviews = await sdk.ats.listAtsInterviews({
  connectionId,
  application_id: application.id,
  limit: 50,
  offset: 0,
  sort: 'updated_at',
  order: 'asc',
});

From AtsInterview, extract:

  • status
  • start_at
  • end_at
  • location

Interview Display Logic

A practical portal layout:

Upcoming Interviews

  • status === 'SCHEDULED'
  • start_at > now

Completed Interviews

  • status === 'COMPLETE'

Awaiting Feedback

  • status === 'AWAITING_FEEDBACK'

Display:

  • Date and time
  • Location (or virtual indicator)
  • Interview status

Do not assume stage transitions based on interview count. The ATS controls stage progression.

Step 4: Handle Real-Time Updates

A 'real-time' portal requires updates when:

  • Application status changes
  • Interviews are scheduled
  • Interviews are updated or cancelled

Use Unified webhooks.

Subscribe to Application Updates

{
  "hook_url": "https://your-app.com/webhooks",
  "connection_id": "<connection_id>",
  "object_type": "ats_application",
  "event": "updated"
}

Subscribe to Interview Updates

{
  "hook_url": "https://your-app.com/webhooks",
  "connection_id": "<connection_id>",
  "object_type": "ats_interview",
  "event": "updated"
}

When a webhook fires:

  1. Validate signature
  2. Upsert record into your database
  3. Recompute portal state
  4. Notify candidate UI (if needed)

Unified retries failed webhook deliveries and uses backoff strategies. Your webhook handler should be idempotent.

Step 5: Initial Sync Strategy

Before enabling webhooks, perform an initial sync.

Use pagination:

  • limit (default 100)
  • offset

Example:

const page = await sdk.ats.listAtsApplications({
  connectionId,
  limit: 100,
  offset: 0,
});

Then store:

  • Applications
  • Interviews
  • Status vocabulary

After initial sync, rely on webhooks for updates.

Optional: Polling Fallback

If webhooks are unavailable, use incremental polling:

updated_gte: lastSyncTimestamp

This allows you to:

  • Retrieve only records updated since your last sync
  • Avoid reloading full datasets

Portal UI Design Recommendations

Keep the portal simple and state-based:

Application Overview

  • Applied date
  • Current stage
  • Stage description

Interview Section

  • Upcoming interviews
  • Past interviews
  • Interview status

Outcome

  • If hired_at exists → show 'Offer Accepted'
  • If rejected_at exists → show 'Application Closed'

Avoid exposing internal recruiter notes or metadata unless intentionally supported.

  1. Initial full sync
  2. Store ATS records in your database
  3. Subscribe to webhooks
  4. Update records on webhook events
  5. Render portal off your internal DB

Do not render directly from live ATS API calls for each page load.

Closing Thoughts

A candidate portal showing real-time interview stages requires:

  • Current application status
  • Interview scheduling visibility
  • Webhook-driven updates
  • Defensive handling of provider variability

Unified's ATS API provides:

  • Normalized application and interview models
  • Stage vocabulary via applicationstatus
  • Webhook support for real-time updates
  • Incremental sync support

The portal layer is your responsibility. Unified ensures you have consistent, structured ATS data to power it.

→ Start your 30-day free trial

→ Book a demo

All articles