Navigate directly to the authenticated When I Work employee roster and return visible employee records with their opaque employee IDs, profile URLs, link labels, and surrounding row text. This supports verifying identities in an external crosswalk without guessing IDs.
Use Cases
Use when the caller needs to read the live When I Work roster or verify employee/driver identities against another system. The caller must have an existing authenticated session or provide credentials through the site's normal login flow; this skill does not embed credentials.
Automation Flow
- Navigate directly to
https://appx.wheniwork.com/userswithwaitUntil: "domcontentloaded". The application may canonicalize tohttps://app.wheniwork.com/users. The older direct routehttps://appx.wheniwork.com/employeesis also valid if the users route is unavailable. - If navigation lands on
https://login.wheniwork.com/, complete the normal approved authentication flow using the caller's session or credentials, then return to the intended roster URL. Do not guess or inject credentials. - Wait for the client-rendered roster, preferably until a known employee/user/profile link exists; allow several seconds after DOM load because the roster is rendered asynchronously. If the roster can legitimately be empty, proceed after a bounded wait and report the resulting count.
- In one page evaluation on the loaded roster, run this extractor:
(() => {
const clean = value => (value || '').replace(/\s+/g, ' ').trim();
const seen = new Map();
const links = [...document.querySelectorAll('a[href]')].filter(link => {
const href = link.getAttribute('href') || '';
return /(?:^|\/)(?:myschedule\/employee|employees?|users?|profiles?)\/[^/?#]+/i.test(href);
});
for (const link of links) {
const href = link.getAttribute('href') || '';
const match = href.match(/(?:^|\/)(?:myschedule\/employee|employees?|users?|profiles?)\/([^/?#]+)/i);
if (!match) continue;
const id = match[1];
const row = link.closest('tr, li, [role="row"]') ||
(link.parentElement && link.parentElement.parentElement) || link;
const record = {
id,
href,
linkText: clean(link.innerText),
rowText: clean(row.innerText || link.innerText),
rowId: row.id || null,
rowClassName: typeof row.className === 'string' ? row.className : ''
};
const previous = seen.get(id);
if (!previous || record.rowText.length > previous.rowText.length) seen.set(id, record);
}
const body = document.body.innerText || '';
const loginPage = /login\.wheniwork\.com$/i.test(location.host) ||
!!document.querySelector('input#email, input[type="email"]');
return {
url: location.href,
authenticated: !loginPage,
employeeCount: seen.size,
employees: [...seen.values()],
bodySnippet: clean(body).slice(0, 2000)
};
})()- Match crosswalk identities using
linkTextandrowText, retaining the opaqueidandhrefas the authoritative When I Work identity references. Do not infer an ID from a name.
Possible Friction Points
- The current direct roster route observed for the live application is
/users; it avoids homepage navigation and is the shortest path to the roster./employeesremains a supported alternate route. - The application may switch between
appx.wheniwork.comandapp.wheniwork.com; treat either authenticated application host as valid. - Employee profile links have used the non-obvious path pattern
/myschedule/employee/{opaque-id}; the users roster may expose equivalent/user/{id},/users/{id},/employee/{id},/employees/{id}, or/profile/{id}links. Capture the ID from the livehref; never fabricate it from an employee name. - Do not recover IDs by scanning nearby HTML for numeric strings. Numeric values near a visible name are not authoritative unless they come from the employee/profile link captured by the extractor.
- The roster is client-rendered, so
domcontentloadedmay occur before employee links appear. Wait for a roster-link selector or a bounded empty-roster outcome. - A login page can be identified by the
login.wheniwork.comhost or an email-login input. Preserve the intended roster URL and return to it after approved authentication. - The same employee ID may appear in multiple nested or duplicated links. The extractor deduplicates by opaque ID and keeps the record with the longest surrounding row text.
- The extractor intentionally returns visible text rather than relying on a fragile name-column selector, because roster row markup may vary. Use
linkTextandrowTextfor identity matching and validate the returned count before updating a crosswalk.