Migrating SEEK Application Export

Migrating SEEK Application Export

The existing SEEK Application Export API allows a partner to retrieve candidate applications for a hirer, including associated documents and screening question responses. It’s also known as “Optimised Apply on SEEK” or simply “SAE”.
SAE has a number of shortcomings:
  • It requires partners to explicitly poll for new applications on a hirer-by-hirer basis. For partners with a large number of hirers this can lead to wasted resources for both the partner and SEEK.
  • It has limited extensibility for passing richer candidate profile data, document types and application questionnaire responses.
  • It has little in common with the existing Ad Posting API or the new SEEK API. This requires duplicated integration effort from partners.
This documentation compares SAE with the SEEK API for application export. For more general information see the application export use case documentation.

Event delivery

The SEEK API replaces per-hirer polling with a new event mechanism. Application export is triggered by the CandidateApplicationCreated event that’s emitted when candidates submit applications.
You can consume CandidateApplicationCreated events three ways:
  1. Creating a webhook subscription that will receive candidate applications for all of your SEEK hirers. This is the recommended option if it fits with your software architecture.
  2. Creating a webhook subscription for each SEEK hirer using application export.
    This replicates the per-hirer event delivery of SAE. However, it requires that you create the appropriate webhook subscription as part of onboarding a new hirer.
  3. Polling an event stream for candidate applications across all your SEEK hirers. This is a fallback for partners that don’t have the capability to receive webhooks.

Data structure

The SEEK API replaces SAE’s JSON and XML responses with a GraphQL schema based on HR Open Standards . For most fields there’s a direct mapping from the previous JSON structure to GraphQL.
You can use SAE’s test.api.seek.com.au to compare data structures with the SEEK API’s GraphQL Playground. They both point to the same internal mock data but use different identifiers:
SAE application ID
Advertiser ID
SEEK API candidate application profile
800000000
10000
seekAnzPublicTest:candidateProfile:apply:7DtW6Q68gk2R4okNGhvg1Y
800000001
10000
seekAnzPublicTest:candidateProfile:apply:4QM5fWQbdekL9gPtPZrzex
800000003
10001
seekAnzPublicTest:candidateProfile:apply:8LKX1QrkJk5JuU2AfW6tsc
800000004
10001
seekAnzPublicTest:candidateProfile:apply:UHeZTe27g1ZJZoHMiwzmPJ
The following annotated examples compare SAE application ID 800000001 against the SEEK API.

Querying SAE

This retrieves application ID 800000001 from test.api.seek.com:
RequestResponse
Copy
GET /v1/advertiser/applications?afterId=800000000&beforeId=800000002&include=ObjectIdentifiers,PrimaryJobSeekingInfo
Host: test.api.seek.com.au

Querying the SEEK API

This is an example query to illustrate how SAE’s fields are represented in the SEEK API. You can remove unneeded fields or select new SEEK API fields based on your requirements.
QueryVariablesResult
query($id: String!) {
  candidateProfile(id: $id) {
    profileId {
      value
    }
    createDateTime
    associatedPositionOpenings {
      positionOpening {
        positionProfiles {
          profileId {
            value
          }
          seekHirerJobReference
          positionOrganizations {
            seekAnzAdvertiserId
          }
          positionUri
        }
      }
      positionUri
    }
    candidate {
      documentId {
        value
      }
      person {
        name {
          given
          family
        }
        communication {
          phone {
            formattedNumber
          }
          email {
            address
          }
        }
      }
    }
    employment {
      organization {
        name
      }
      positionHistories {
        start
        end
        title
      }
    }
    attachments {
      seekRoleCode
      url
    }
  }
}

Transitioning existing hirers

The SEEK API and SAE can be safely run in parallel for the same hirer. Each candidate application will appear in both integrations but with a different identifier and timestamp. This requires care to avoid duplicate candidate applications appearing in your software.
SEEK supports three methods to transition existing hirers from SAE to the SEEK API. You can choose the method that best fits your software’s architecture.

Method 1: De-duplicating applications

Candidate application
Candidate application
Yes
No
SAE
Seen application ID?
SEEK API
Ignore
Store candidate application
SAE can return candidate application profile IDs in addition to its legacy identifiers. Your software can opt-in to this by adding &include=ObjectIdentifiers,PrimaryJobSeekingInfo to your SAE request URLs.
You can export candidate applications from both integrations and filter out candidate application profile IDs that have already been exported. Once you validate your SEEK API integration is working correctly you can safely disable your SAE integration.
This is the recommended method if it’s feasible to modify your existing SAE integration.

Method 2: Filtering by job ad

Candidate application
Candidate application
No
No
Yes
Yes
SAE
Old job ad?
SEEK API
New job ad?
Ignore
Ignore
Store candidate application
You can continue to use SAE for existing job ads while starting to use the SEEK API for newly posted ads. Your software will need to filter candidate applications based on their associated position to ensure they came from the intended integration.
This is the recommended method if your software supports multiple applications from the same candidate to the same position. However, this requires running your SAE integration until the hirer’s existing job ads have closed.

Method 3: De-duplicating candidates

Candidate application
Candidate application
Yes
No
SAE
Seen email address?
SEEK API
Ignore
Store candidate application
You can export candidate applications from both integrations and de-duplicate based on the candidate’s email address. SEEK requires candidates to sign in with their email address before using SEEK’s native apply form. This allows the candidate’s email address to uniquely identify them across both integrations.
While SEEK doesn’t prevent multiple applications from the same candidate to the same position, this is rare in practice. If your software is already de-duplicating candidates this is the simplest method.

Potential gotchas

Serving attachment downloads

Attachments may be downloaded one of two ways:
  • At the time of candidate application.
    In this scenario, your software retrieves the application and its related attachments upfront, and does not need to make any subsequent calls to SEEK. This allows you to cleanly cut over from SAE to the SEEK API without any disruption to existing application data.
  • On demand.
    In this scenario, your software keeps track of the attachment download URLs associated with each application. This means that it will have to store a different URL based on whether the application was retrieved from SAE or the SEEK API, and be able to download attachments from either API, including using the appropriate credentials.
    Support for SAE attachment downloads may be dropped after a reasonable period of time. An attachment will remain for 180 days after the close date of its associated job ad.

Integer identifier continuity

We recommend that you use our new string object identifiers as they provide important benefits. However, if it’s not immediately feasible to switch your software over to a more expansive data type, you can generate your own backward-compatible identifiers. This gives you more control in selecting the appropriate data type for now and also evolving your software in future.
Database systems often support collision-safe number generation. The following MySQL example generates a numeric identifier using an AUTO_INCREMENT column in place of the old SAE application ID, and also applies a unique constraint on the new object identifier for deduplication.
SQL
Copy
-- Simplified representation of an existing table in your database
CREATE TABLE candidate_application (
  old_numeric_id INT  NOT NULL,
  new_object_id  TEXT NOT NULL,
  PRIMARY KEY (old_numeric_id),
  UNIQUE KEY  (new_object_id)
);
-- A new table for generating your own incremental identifiers
CREATE TABLE candidate_application_id_generator (
  id INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (id)
);
-- Start your own identifiers at a reasonable jump from existing SAE identifiers
ALTER TABLE
  candidate_application_id_generator AUTO_INCREMENT = 123;
-- For SEEK API applications, generate and insert a numeric identifier
-- This is rudimentary and will throw an error on a duplicate object identifier
INSERT INTO candidate_application_id_generator (id) VALUES (DEFAULT);
INSERT INTO candidate_application (old_numeric_id, new_object_id)
VALUES
  (
    LAST_INSERT_ID(), -- This is safe even with concurrent connections
    'seekAnzPublicTest:candidateProfile:apply:7DtW6Q68gk2R4okNGhvg1Y'
  );