Try it
<script src="https://one-career.com/embed/v1.js" async></script>
<oc-jobs org="one-career"></oc-jobs>Loading the embed script…
Install
<!-- once per page, anywhere -->
<script src="https://one-career.com/embed/v1.js" async></script>
<!-- then any number of widgets -->
<oc-jobs org="your-org-slug" page-size="8"></oc-jobs>
<oc-company-grade company="your-org-slug" compact></oc-company-grade>Your organisation slug is the short name of your verified organisation (for example one-career). It is also shown in Organisation console → Developers.
Widgets
| Element | Attributes | Shows |
|---|---|---|
<oc-jobs org="slug"> | org (required). See the job board options below. | A full career-page job board: search, filter chips with counts (type, work mode, location), open / recently closed / all roles, up to 200 roles with “Show more” or numbered pages, list, grid or compact layouts. Each role opens its One-Career page, where Apply asks the visitor to sign in. |
<oc-company-grade company="slug"> | company (required), compact | Your One-Career employer grade (A+ … F), built from reviews and hiring outcomes, plus your verified status and number of open jobs. |
<oc-verified-badge card="…"> | card (required), sig (from the QR, for a full check) | A live check of a One-Career ID card, staff card (OCS-) or organisation card (OCO-). Revoked or expired cards show as not valid. |
<oc-apply-button posting="uuid"> | posting (required), label | A button that opens the posting on One-Career. It shows “Applications closed” once the posting closes. |
<oc-profile-card share="pc_…"> | share (required) | A candidate's profile card, using a link the candidate created and can turn off at any time. It shows only the fields they chose. |
Job board options
| Attribute | Values | What it does |
|---|---|---|
status | open · closed · all | Which roles to list. closed = closed in the last 180 days (shown with a Closed tag and no apply link). Default open. |
page-size | 1–100 | Roles per page or per “Show more” (default 10). limit still works as an alias. |
max | 1–200 | Most roles the board will ever show (default 200). |
pagination | more · pages | “Show more” button (default) or Previous / Next pages. |
layout | list · grid · compact | Cards in a column, a responsive grid, or one line per role. |
filters | search,type,mode,location,status | Controls the visitor sees. Chips appear only when there is more than one choice. filters="" hides them all. |
q · types · modes · location | text · comma lists | Presets, e.g. types="full_time,internship" modes="remote" location="Chennai". Add lock so visitors can't change a preset. |
group | none · type · location | Group roles under headings. |
show | location,type,mode,salary,skills,posted,closes | Which details each card shows (default all but closes). |
heading · empty-text · apply-label | text | Your wording. heading="" hides the heading; apply-label adds a button to each open role. |
link · target | details|apply · _blank|_self | Where a card goes (both open the role on One-Career) and whether in a new tab (default). |
locale | e.g. en-IN, en-US, de-DE | Language for dates and pay (default: the visitor's browser). |
sync-url | flag | Keeps the visitor's filters in the page address (?oc_types=…), so filtered links can be shared and Back works. |
<oc-jobs org="acme" status="all" page-size="20" layout="grid"
filters="search,type,location,status" types="full_time,part_time"
heading="Join us" apply-label="Apply"></oc-jobs>Applying always happens on One-Career: the role page asks the visitor to sign in (or create an account) and brings them straight back to the application. The widget never collects personal data on your site.
Events, methods and parts
Every job board fires DOM events (they bubble out of the Shadow DOM), exposes a small API, and names its parts so you can restyle anything.
const board = document.querySelector("oc-jobs");
// analytics, or your own modal instead of opening One-Career
board.addEventListener("oc-jobs:load", (e) => console.log(e.detail.total, e.detail.items));
board.addEventListener("oc-jobs:click", (e) => {
gtag("event", "job_click", { job_id: e.detail.job.id });
// e.preventDefault(); // stop the link and handle it yourself
});
board.addEventListener("oc-jobs:filter", (e) => console.log(e.detail.filters));
board.addEventListener("oc-jobs:error", (e) => console.warn(e.detail.status, e.detail.message));
// drive it from your own UI
board.setFilters({ types: ["internship"], modes: ["remote"], q: "react" });
board.refresh(); // fetch again, skipping the cache
board.filters; // { q, status, types, modes, location }/* ::part() reaches inside the Shadow DOM */
oc-jobs::part(card) { border-width: 2px; }
oc-jobs::part(card-closed) { filter: grayscale(1); }
oc-jobs::part(title) { font-size: 18px; }
oc-jobs::part(filter-on) { background: black; }
/* also: box heading count filters search filter list meta tag salary badge apply group pager empty */// load the script once (e.g. in your layout)
<Script src="https://one-career.com/embed/v1.js" strategy="afterInteractive" />
// then use the element anywhere; for TypeScript add:
// declare global { namespace JSX { interface IntrinsicElements { "oc-jobs": any } } }
<oc-jobs org="acme" status="all" page-size="20" sync-url />Something not showing? Open the browser console: the widget explains wrong slugs, invalid attribute values and blocked domains there, prefixed with
[one-career embed].Styling
Widgets render in a Shadow DOM: your CSS can't break them and theirs can't leak into your page. Theme them with CSS variables on the element or any ancestor, and set theme="light|dark" (default auto follows the visitor's system).
oc-jobs {
--oc-accent: #0f766e; /* buttons, hover borders, grade tile */
--oc-bg: #ffffff; /* card background */
--oc-fg: #0f172a; /* text */
--oc-muted: #64748b; /* secondary text */
--oc-border: #e2e8f0;
--oc-radius: 16px;
--oc-font: "Inter", system-ui, sans-serif;
}Privacy and security
- Widgets read only public, CORS-enabled endpoints. They set and read no cookies and track nobody.
- All data is inserted as text, never as HTML, so a job title can't inject markup into your page. Links open in a new tab with
rel="noopener noreferrer". - Allowed domains: in the organisation console you can list the sites where your job board and grade may appear (e.g.
careers.acme.com,*.acme.com). Everywhere else they show a short notice instead. Leave the list empty to allow any site. - Nothing iframes your site and nothing is iframed, except the existing
/embed/<username>verified portfolio card, which may be framed anywhere.
Prefer your own UI? Use the same public endpoints directly:
GET /api/v1/companies/{slug}/jobs, /companies/{slug}, /verify/card/{number}. See the API reference.