When positions are created and updated in your software,
propagate those changes to SEEK.Click here to view the sequence diagramUse the GraphQL Note Requests will be routed to the Playground environment if all the emails
included in
Note Editing a job ad through any channel other than Ad Sync (e.g. directly
on the SEEK Employer website or via classic or Enhanced Job Posting) will break
the sync—future updates to the position through Ad Sync will no longer propagate
to the job ad.Directional Ad Sync may be extended in a later release to provide an indicator for job ads that were modified outside of Ad Sync, allowing your software to redirect hirers to make future updates to SEEK through the same channel.
When available, you would be able to query the
* If your software collects remuneration and work arrangement data, it must be shared with SEEK as this will significantly improve the quality of the posted job ad.To reduce job ad duplication, provide a unique stable identifier that your software uses to uniquely identify each position.Ensure that your software provides the same Directional Ad Sync may be extended in a later release to allow your software to share positions from a hirer that is yet to onboard to SEEK.
A new SEEK hirer ID will be provisioned and returned in the response;
store this ID and use it when sharing subsequent positions for the same hirer.Provide city or suburb granularity for each position.
Precisely locating positions helps candidates search for the most relevant jobs.If a hirer is recruiting for a remote position that is not tied to a specific geographical location, set Provide the pay type, salary range, and description of the remuneration package.Optionally provide When implementing Ad Sync in your software,
you will need to make two related design decisions:
Your software is forbidden from indiscriminately re-synchronising all positions at each interval;
Ad Sync must only be triggered for positions that actually changed within the period.While most of our code samples provide a single position to the
syncPositions mutation to share position data with SEEK.
This mutation functions as a PUT operation - always provide the position’s complete state, as any field you omit will be cleared rather than left unchanged.GraphQLVariablesSuccessFailure
CopyGraphQL Explorer
mutation SyncPositions($input: SyncPositionsInput!) {
syncPositions(input: $input) {
positions
errors {
seekPartnerPositionId
error
}
}
}postingRequester.personContacts.communication.email have the
reserved testing domain of example.org.A successful response confirms SEEK has accepted the position for processing - it doesn’t guarantee a job ad has been posted yet.
Subscribe to lifecycle events to detect when the job ad goes live, and see Display job ads for guidance on rendering job ad status in your software.Ad Sync job ads can be updated in three ways via the SEEK API.
The method used determines whether future Ad Sync syncs will continue to propagate automatically.Method | Future syncPositions calls work? |
|---|---|
Yes | |
No | |
No |
positionProfile after a PositionProfileUpdated event to check this indicator, detect when a job ad has been updated via a channel other than Ad Sync, and flag the job ad in your software as no longer synced.You can use the same syncPositions mutation to update a position as you can to post one.
SEEK determines whether to post a new job ad or update an existing one based on the position’s seekPartnerPositionId.Forward the position’s full state to the same syncPositions mutation whenever it changes in your software to keep the job ad in sync automatically.Your software should continue syncing a position for as long as its job ad is live on SEEK.After a PositionProfileClosed event has occurred for a position, avoid calling the syncPositions mutation for it again unless a hirer explicitly chooses to re-post it — see Re-posting a job.
Doing so risks creating another job ad on SEEK for the same position.Ad Sync may infer values for fields such as positionLocation, positionFormattedDescriptions (e.g. the SearchSummary and SearchBulletPoint entries), offeredRemunerationPackage, job category*, or seekWorkType that your software didn’t originally supply.After a PositionProfilePosted or PositionProfileUpdated event, consider querying positionProfile to retrieve these inferred values, so you can display what’s currently live on SEEK to the hirer and/or persist them for re-use in a subsequent syncPositions mutation call.
See Querying a job ad for a full query and response example covering these fields.If you don’t persist them, Ad Sync may re-infer the values on a subsequent edit, which may produce a different result to what’s currently live on SEEK.* Not all inferred fields can be supplied back to the syncPositions mutation - job category, for example, is always inferred by SEEK and has no corresponding input field.
You may still want to surface it to the hirer, e.g. as a read-only field, even though they can’t edit it directly.Set postingInstructions.end to now or a time in the past to close the position.
SEEK will take the job ad offline, and a subsequent PositionProfileClosed event lets your software reflect the closed status to the hirer.Closing is a terminal state — see Re-posting a job to re-advertise the position.You can also temporarily hide a posted job ad without closing it by setting suspend.Directional Ad Sync may be extended in a later release to emit a PositionProfileUpdated event both when a job ad is suspended and when it’s later reactivated, allowing your software to display the current status of the job ad to the hirer.Directional Ad Sync may be extended in a later release to support a hirer explicitly re-posting an expired position with the same seekPartnerPositionId.
If your software supports this, call the syncPositions mutation with postingInstructions.end set to a time in the future or omitted.Since this creates a new job ad on SEEK, it will emit a PositionProfilePosted event with a new positionProfileId, distinct from the one assigned to the closed job ad, even though the seekPartnerPositionId stays the same.Hirers can alternatively update a live Ad Sync job ad using Enhanced Job Posting.
As noted above, this breaks the automatic sync from your requisition—once a job ad has been edited this way, subsequent syncPositions calls will no longer update it.See Update a job ad for the Enhanced Job Posting update flow.Hirers can also update a live Ad Sync job ad using Classic Job Posting.
As with Enhanced Job Posting, this breaks the automatic sync from your requisition.Pre-populate your requisition with the job ad’s current fields via Querying a job ad, so the hirer isn’t left to re-enter details Ad Sync already posted.See Updating a job ad for the Classic Job Posting update flow.Ad Sync uses a similar data structure to the postPosition mutation.A brief summary of important fields is provided below.Field | Path | Example | Requirement |
|---|---|---|---|
Identifier | seekPartnerPositionId | Mandatory | |
Hiring organization | postingRequester | Mandatory | |
Title | positionTitle | Senior Business Analyst | Mandatory |
Location | positionLocation | Mandatory | |
Description | positionFormattedDescriptions | Mandatory | |
Created date | createdDateTime | 2048-01-01T09:45:32.617Z | Mandatory |
Updated date | updatedDateTime | 2048-01-01T09:45:32.617Z | Mandatory |
Work arrangements | seekWorkArrangementCodes | OnSite | Mandatory* |
Salary | offeredRemunerationPackage | Mandatory* | |
Application URL | postingInstructions.applicationMethods | Mandatory to link out | |
Search bullet points | positionFormattedDescriptions | Recommended | |
Search summary | positionFormattedDescriptions | Recommended | |
Closing date | postingInstructions.end | 2048-01-31T00:00:00.000Z | Recommended |
Work type | seekWorkType | Recommended | |
Suspend | postingInstructions.suspend | true | Optional |
Partner metadata | seekPartnerMetadata | stringified metadata | Optional |
Posting method | seekPostingMethod | Other | Optional |
Application questionnaire | applicationQuestionnaire | Optional |
Request snippet
Copy
"REQ-123"seekPartnerPositionId across all operations relating to the position.When querying for position profiles through the SEEK API, this identifier is returned under seekHirerJobReference to allow you to correlate SEEK data with positions in your software.Use this field in combination with seekPartnerMetadata to link positions and job ads between your software and SEEK.When sharing a position, provide:seekOrgReference: A stable identifier that uniquely identifies the hiring organization in your softwareseekOrgName: The name of the organizationseekAdSyncId: The ID provided by SEEK when a hirer onboards to Ad SyncpersonContacts: The contact person for the position
seekSubOrgReference: For a hiring organization with multiple SEEK accounts, provide an identifier for the specific business unit or subsidiary that owns the position. Ad Sync will use this field to select the appropriate SEEK account. See the next page on position routing for more information.seekSubOrgName: The name of the sub organization
Existing SEEK hirer
Copy
{"seekOrgReference": "abc-123",
"seekOrgName": "Acme Corp",
"seekAdSyncId": "seek-adSync-gKBnHR6qtRFC",
"seekSubOrgReference": "AcmeCorp-AU",
"seekSubOrgName": "Acme Corp Australia",
"personContacts": {
"name": { "formattedName": "Francis Admin" },
"roleCode": "AccountAdministrator",
"communication": {
"email": [{ "address": "francis.admin@example.com" }],
"phone": [{ "formattedNumber": "1800 160 401" }]
}
}
}Request snippetResponse snippet
Copy
{"communication": {
"address": {
"line": "Wallaman Falls, Lookout Rd",
"city": "Wallaman",
"countrySubDivisions": {
"type": "State",
"value": "QLD"
},
"postalCode": "4850",
"country": "AU"
},
"phone": {
"formattedNumber": "1900 654 321"
}
},
"name": "Acme Corp",
"personContacts": {
"name": { "formattedName": "Francis Admin" },
"roleCode": "AccountAdministrator",
"communication": {
"email": [{ "address": "francis.admin@example.com" }],
"phone": [{ "formattedNumber": "1800 160 401" }]
}
},
"seekPartnerHirerId": "abc-123"
}Structured dataGeolocation
Copy
{"city": "Wallaman",
"countrySubDivisions": {
"type": "State",
"value": "QLD"
},
"postalCode": "4850",
"country": "AU"
}seekWorkArrangementCodes to Remote.
A location is still required for a remote position;
this can be set to the headquarters or local branch of the hirer’s organization.SEEK’s job posting APIs currently support one location per posted position.If your ATS supports multi-location requisitions and you want a job ad to appear in multiple locations, materialise each target location as a separate position in your own system and call the mutation once per location.
This keeps salary and other location-dependent fields unambiguous while still allowing you to offer a streamlined multi-location experience in your product.Directional Ad Sync may be extended in a later release to allow your software to share positions with multiple locations, which SEEK will post as a single job ad appearing in all specified locations.Descriptions for the position are supplied in an array.Provide a complete representation of the position in AdvertisementDetails,
including paragraphs and formatting to make the content easier to read.
Do not truncate with … or similar.Request snippet
Copy
[// Short description to be shown in search results
{
"descriptionId": "SearchSummary",
"content": "Seasoned BA sought to lead strategic initiatives."
},
// Three bullet points to display in search results
{
"descriptionId": "SearchBulletPoint",
"content": "Stakeholder management and facilitation"
},
{
"descriptionId": "SearchBulletPoint",
"content": "Process mapping and requirement elicitation"
},
{
"descriptionId": "SearchBulletPoint",
"content": "Data-driven decision making"
},
// Detailed description to appear on a job ad
{
"descriptionId": "AdvertisementDetails",
"content": "<p>Acme Inc is seeking a business analyst to partner with business and technology teams to deliver high-impact, data-informed change.</p><p>You will lead discovery, define clear and testable requirements, map current and future processes, and support delivery through to adoption.</p><p>Bring strong stakeholder engagement, facilitation skills, and a pragmatic approach to complex problem solving.</p>"
}
]Request snippet
Copy
{"basis": "Salaried",
// 100,000–130,000 Australian dollars per year
"ranges": {
"minimumAmount": {
"value": 100000,
"currency": "AUD"
},
"maximumAmount": {
"value": 130000,
"currency": "AUD"
},
"interval": "Year"
},
// Remuneration description visible to the candidate
"descriptions": ["Competitive salary, plus super"]
}- The pay type is expressed using a combination of two fields:
- The
basisdefines how the remuneration for the position is calculated - The
intervaldefines the period of time the minimum & maximum amounts are calculated over
basismust correspond to theinterval:- When the
basisisHourly, theintervalmust beHour. - When the
basisisSalaried, theintervalmust beMonthorYear. - When the
basisisSalariedPlusCommission, theintervalmust beYear.
basisandintervalare not one of the supported combinations above, the salary will not be included on the job ad. - The salary range is specified in the major currency unit (e.g. dollars)The range is used to provide more relevant job search results to candidates, but the monetary values in
minimumAmountandmaximumAmountare not visible in search results nor on the job ad. - The remuneration description is displayed to candidatesThe description should be a short summary of the package, including further benefits such as bonus options and superannuation. Note that this field has a maximum length of 50 characters, which roughly corresponds to a single English sentence.SEEK may display the supplied
currencyandintervalalongside the description for clarity.
applicationUri.
This replaces SEEK’s Apply Form with an external apply form,JSON
Copy
{// Set explicitly to an external apply form
"applicationMethods": [
{
"applicationUri": {
"url": "https://example.com/position/123/apply"
}
}
]
// Other posting instruction fields
}postingInstructions.suspend to control the visibility of a posted job ad.- If
postingInstructions.suspendistrue, the job ad will be temporarily suspended and no longer appear on SEEK. - If
postingInstructions.suspendisfalse, the job ad will be reactivated. - If
postingInstructions.suspendis omitted, it will be defaulted tofalse.
seekPostingMethod to indicate that a position is being shared with SEEK through another channel, such as a classic or Enhanced Job Posting integration.When seekPostingMethod is set to Other, Ad Sync will not post the position to SEEK and will not manage any resulting job ad.Optionally provide a seekWorkType to indicate the work type for the position.The four work types that SEEK recognises are:FullTimePartTimeCasualContractTemp
seekWorkType other than the four recognised types, or if the field is omitted, SEEK will infer the work type from the position description and other details.The createdDateTime and updatedDateTime fields represent when the position was created and last updated in your software, respectively.They must not represent when the position was shared with SEEK via Ad Sync.Directional At this time a questionnaire will not be created for data sent through for this field.
This will be implemented in a future release of the SEEK API.A job ad may specify a questionnaire to include in SEEK’s Apply Form.
Candidates complete the questionnaire as part of their job application,
and their responses are made available through the Optimised Apply use case.
Questionnaires are rendered on SEEK’s candidate website and in our mobile apps.By integrating questionnaires into your posting flow, you can enable hirers to:- Add custom questions.
- Select preferred response choices for each question.
- Attach a company privacy policy if applicable.
Request snippet
Copy
[// Single select question component
{
"componentTypeCode": "Question",
"question": {
"componentTypeCode": "Question",
"questionHtml": "How many years of experience do you have in this field?",
"responseTypeCode": "SingleSelect",
"value": "experience-years",
"responseChoice": [
{
"text": "Less than 1 year",
"value": "lt-1",
"preferredIndicator": false
},
{
"text": "1-3 years",
"value": "1-3",
"preferredIndicator": false
},
{
"text": "3-5 years",
"value": "3-5",
"preferredIndicator": true
},
{
"text": "5+ years",
"value": "5-plus",
"preferredIndicator": true
}
]
}
},
// Multi select question component
{
"componentTypeCode": "Question",
"question": {
"componentTypeCode": "Question",
"questionHtml": "Which of the following technologies are you proficient in?",
"responseTypeCode": "MultiSelect",
"value": "tech-proficiency",
"responseChoice": [
{
"text": "TypeScript",
"value": "typescript",
"preferredIndicator": true
},
{
"text": "Python",
"value": "python",
"preferredIndicator": false
},
{
"text": "Go",
"value": "go",
"preferredIndicator": false
},
{
"text": "Java",
"value": "java",
"preferredIndicator": false
}
]
}
},
// Free text question component
{
"componentTypeCode": "Question",
"question": {
"componentTypeCode": "Question",
"questionHtml": "Please describe why you are interested in this role.",
"responseTypeCode": "FreeText",
"value": "interest-reason"
}
},
// Privacy consent component
{
"componentTypeCode": "PrivacyConsent",
"privacyConsent": {
"componentTypeCode": "PrivacyConsent",
"value": "privacy-consent-1",
"privacyPolicyUrl": {
"url": "https://example.com/privacy-policy"
},
"descriptionHtml": "I agree to the collection and processing of my personal data."
}
}
]- Whether to share positions in near real time or on a periodic interval
- Whether to share positions individually or in batches
updatedDateTime that represents when the last update to the position actually occurred in your software;
it must not represent when the batch of positions is later sent to SEEK.SEEK will use the updatedDateTime to determine which updates to process and which to ignore, ensuring that only the most recent update to each position is reflected on SEEK.Event | Timestamp | Use as updatedDateTime? |
|---|---|---|
Hirer saves change to position description | 2048-01-01T09:45:32.617Z | |
Partner synchronises position updates for the past 1 hour | 2048-01-01T10:00:00.000Z |
syncPositions mutation for simplicity,
multiple positions can be shared at once.This is useful if your software may share more than one position at a time,
including if it:- Synchronises positions on a periodic interval rather than in near real time
- May modify multiple positions at once (e.g. due to process automation)
- Supports resending historical data (e.g. to correct data quality issues)
syncPositions operation.
If you have more than 100 positions to send,
split them into chunks of 100 and run multiple operations,
monitoring the SEEK API responses for rate limiting errors.