# SkillsDB > SkillsDB is a skills intelligence platform for enterprise HR teams. It tracks skills, assesses proficiency, analyzes gaps, builds career frameworks, manages certifications, and enables workforce planning. Trusted by Fortune 500 companies since 2008. SOC2 Type II certified and GDPR compliant. --- ## Website Overview ### Homepage SkillsDB is the skill and competency platform for L&D. Build winning teams with skills analytics, targeted training, workforce planning, and more. Trusted by AXA, Boeing, Ryder, Notre Dame, and 30+ global organizations since 2008. ### How It Works SkillsDB provides a 7-step framework for implementing a skills-driven organization: 1. Identify use cases — focus on critical business priorities 2. Build frameworks — create competency and career pathways 3. Assessment and data collection — conduct manager and employee skill surveys 4. Gap analysis — analyze skill disparities across the organization 5. Personalized development — create tailored upskilling plans 6. Training execution — deploy organizational training 7. Talent development — leverage data for mentors, experts, and succession planning ### Perspective SkillsDB believes skills-first thinking is the foundation of modern workforce strategy. Professional skills have a shelf life of just 5 years. Organizations should ask "What skills do we need, and what skills do we have?" rather than starting with training content. Career ladders are outdated — the future requires skill-based clarity with transparent pathways. Learning culture must be treated as strategically critical, not outsourced to generic content libraries. ### Company URL: https://skillsdb.com/company SkillsDB helps global teams build learning culture at scale. Founded in 2008, trusted by Fortune 500 organizations for skills and competency management. Mission: Make learning culture universal — helping L&D teams realize the full potential of the people they serve. Career clarity is the norm SkillsDB is building toward — where people can rise to any level through diligent skill and competency development. Company principles: 1. Deliver learning culture, not software — look past the product; take direct responsibility for customer outcomes 2. Be hyper-responsive — customers are accountable to entire organizations; respond with extreme urgency 3. Become indispensable — find the need behind the need; be reliable, predictable, and highly adaptable 4. Keep tight tolerances — speed and quality begin with precision; focus on simplicity; anticipate your audience 5. Love what you make — craft comes from deeply considering users and their ultimate needs ### Contact URL: https://skillsdb.com/contact Contact hub page routing visitors to sales or support, plus links to the help center and LinkedIn community. Contact emails: support@skillsdb.com and sales@skillsdb.com. Sales inquiries: https://skillsdb.com/contact/sales — Request a demo, learn about pricing, or get onboarding help. Support inquiries: https://skillsdb.com/contact/support — Ask product questions, report problems, or leave feedback. ### Whitepaper URL: https://skillsdb.com/whitepaper Gated whitepaper download on competency-based training programs, upskilling strategies, and employee development best practices. ### Core Platform Capabilities - Skills tracking and taxonomy management - Proficiency grading (employee, manager, and benchmark grades) - Career frameworks with levels, sections, and skill benchmarks - Gap analysis between current proficiency and role requirements - Manager and self-assessments - Skills matrix — interactive grid of people × skills - Training approval workflows with evidence and expiration tracking - Certification management and compliance tracking - Skill and people flags (Expert, Mentor, Trainer, custom designations) - Employee surveys with skill-updating question types - Learning plans with kanban boards and progress tracking - Document management (Playbooks, SOPs, Work Instructions, Policies) - Search and explore — find people by skills, flags, certifications, documents - Analytics and reporting dashboards - Excel export across all data views - GraphQL API - SCIM provisioning and SSO - multi-language support supported --- ## Learn (reference entries) Short reference entries on the vocabulary of skills management. Each defines one term, gives the facts a reader looks up, and links to the long-form guide. ### Competency Management Software URL: https://skillsdb.com/learn/competency-management-software Competency management software is a system that defines the competencies each role requires, records assessed proficiency against them with evidence, and produces the gap, training, and audit records that prove people are competent for the work they do. Competency management software exists to make competence provable. Regulated and safety-critical operations must show not just that a person completed training, but that they demonstrated the required proficiency on the current version of a procedure, that the demonstration is dated and evidenced, and that expiring qualifications are tracked before they lapse. The software holds a competency framework per role, records assessments with method and evidence, tracks proficiency and currency over time, computes gaps, generates the training matrix, and keeps an audit trail of every change. It is a neighbor of the skills intelligence platform category with a compliance emphasis: the same primitives of skills, levels, roles, and assessments, organized so an auditor's question can be answered from the record rather than reconstructed from spreadsheets and email. Full guide: https://skillsdb.com/blog/how-to-choose-competency-management-software ### Job Roles and Job Architecture URL: https://skillsdb.com/learn/job-architecture A job architecture is the structured hierarchy of job families, levels, and roles that attaches to every role the skills it demands and the proficiency level expected for each. Job architecture is the framework an organization uses to describe its work in a consistent way: a small number of job families group related roles, a set of levels defines progression within each family, and each role at each level carries a profile of required skills with target proficiency levels. It replaces the sprawl of job titles, which are labels, with roles, which are definitions. The value of the architecture in a skills-based organization is that it connects two records that are usually kept apart: what a role requires and what a person can do. When both are expressed in the same skills library on the same proficiency scale, the gap between them can be computed for any person against any role, which is what makes internal mobility, succession slates, and workforce planning operate on evidence instead of on titles and tenure. Full guide: https://skillsdb.com/blog/job-roles-and-job-architecture ### Proficiency Levels URL: https://skillsdb.com/learn/proficiency-levels Proficiency levels are the ordered steps on a scale that state how well a person can perform a specific skill, each step described by observable behavior rather than by tenure or self-belief. A proficiency level is a position on a defined scale that describes what a person can reliably do with one skill, right now. Levels convert a skill from a yes-or-no label into a measurement that can be compared between people, tracked over time, and matched against what a role requires. Each level needs an anchor: a short statement of the behavior an assessor would observe at that level, such as "performs the procedure unsupervised on routine cases" or "diagnoses novel failures and coaches others." Anchors are what make two assessors agree. Organizations typically use one scale across the whole skills library so that a level 3 in one skill means the same degree of independence as a level 3 in another. Required levels are set per role, assessed levels are recorded per person, and the difference between them is the skill gap. Full guide: https://skillsdb.com/blog/proficiency-levels-scales-examples ### Skills Assessment URL: https://skillsdb.com/learn/skills-assessment A skills assessment is a recorded judgment of a person's proficiency level on a specific skill, made by a stated method on a stated date so the result can be compared and defended. A skills assessment produces one data point: this person, this skill, this level, assessed this way, on this date. It differs from a performance review, which judges outcomes across a period, and from a pre-employment test, which screens candidates on a fixed instrument. Workforce skills assessment is ongoing and role-linked: the required level comes from the role profile, the assessed level comes from the method chosen for that skill, and the gap between them drives development and staffing. The method matters as much as the score. A self-rating and a practical test can both return a 3, but they carry different weight, so the record should state which produced it. Assessments accumulate into the skills inventory, and their dates drive the reassessment schedule that keeps perishable skills current. Full guide: https://skillsdb.com/blog/skills-assessment-methods-and-tools ### Skills Intelligence Platform URL: https://skillsdb.com/learn/skills-intelligence-platform A skills intelligence platform is the software that serves as the system of record for skills: it defines an organization's skills, verifies who holds them at what level, computes the gaps against roles, and connects those gaps to planning and learning. A skills intelligence platform holds skills data as its primary object rather than as an attribute of an employee profile or a course catalog. It maintains the organization's skills library in its own language, records assessed proficiency per person per skill with method and date, states required levels per role, and derives gaps, matrices, succession slates, and learning plans from those records. The word "intelligence" distinguishes it from skills tracking: tracking stores what people say they can do, while intelligence verifies it, keeps it current, and turns it into decisions. The category now includes several structurally different kinds of software, from HCM suite modules to talent marketplaces to inference engines. They converge on the same five capabilities and differ mainly in whether the underlying skills data is assessed or inferred, and whether the system can prove either. Full guide: https://skillsdb.com/blog/skills-intelligence-platforms-buyers-landscape ### Skills Inventory URL: https://skillsdb.com/learn/skills-inventory A skills inventory is the dated, per-person record of which skills each employee holds, at what proficiency level, on what evidence. A skills inventory is a structured record, one entry per employee, listing the skills that person holds, the assessed proficiency level for each, the method and date of assessment, and any supporting evidence such as a certification or a supervised sign-off. It is organized around the person, which distinguishes it from a skills matrix (organized around a team) and a skills database (organized around the organization). The inventory is the source the other two are built from: a matrix is a view of several inventories against a role's requirements, and a database is the queryable store of all of them over time. An inventory is only as useful as it is current. Because skills decay and roles change, each entry needs a reassessment date, and the inventory needs an owner responsible for keeping it accurate. Full guide: https://skillsdb.com/blog/skills-inventory-how-to-build ### What Is a Skill? URL: https://skillsdb.com/learn/skills A skill is a specific, observable ability to perform a task to a defined standard, expressed with a proficiency level so it can be compared across people and over time. A skill is the smallest unit of capability an organization can name, measure, and develop. It describes something a person can do, not something they know about or a trait they have, and it is written narrowly enough that two assessors watching the same work would reach the same rating. "Configure a managed switch to site standard" is a skill. "Networking" is a category. "Detail-oriented" is a trait. The distinction matters because everything downstream depends on it: a skills matrix is a grid of skills, a gap is the distance between a required and an assessed skill level, and a development plan is a sequence of skills to raise. A skill without a proficiency level is only a label. Attached to a level and a date, it becomes a data point that can support staffing, succession, and compliance decisions. Full guide: https://skillsdb.com/blog/what-are-skills-types-and-skill-sets ### What Is a Competency? URL: https://skillsdb.com/learn/competencies A competency is a named, leveled cluster of abilities, knowledge, and behavior a role needs to deliver a specific work outcome, written so an assessor can judge how well someone performs it. A competency groups the things a person must know, do, and show to achieve a result the organization depends on. Where a skill names one ability, a competency names the outcome and the abilities behind it. "Configure a firewall rule" is a skill; "Deliver network changes without unplanned outages" is a competency that draws on several skills plus the judgment to sequence and verify them. Every competency carries a scale, usually the same 0 to 5 scale used for skills, with level descriptors written as observable behavior rather than adjectives. A role states the level it requires for each competency; an assessment records the level a person demonstrates; the difference is the gap that development closes. Competencies are written in the organization's own language, because a definition imported from a generic catalog rarely matches how the work is actually done and is quietly ignored by the managers meant to use it. Full guide: https://skillsdb.com/blog/how-to-create-a-competency-definition-for-your-organization ### Skills vs. Competencies vs. Proficiency URL: https://skillsdb.com/learn/skills-vs-competencies Skills, competencies, and proficiency are three different kinds of record: a skill is a unit of ability, a competency is an outcome-shaped bundle of them, and proficiency is the measurement applied to either. The three terms answer three different questions. A skill answers "what can this person do?" and is the smallest unit an organization tracks, such as reading a wiring schematic. A competency answers "what outcome does the role need, and what combination of skills, knowledge, and behavior produces it?" and is defined per job family in the organization's own words. Proficiency answers "how well, right now?" and is a level on a scale attached to a skill or a competency, always with a date and a method behind it. Programs get into trouble when the terms blur: skills lists grow into unmanageable catalogs because competencies were never defined, competencies are written too broadly to assess because the skills inside them were never named, and proficiency becomes one number per person because it was never attached to anything specific. Keeping the three separate is what lets gaps, matrices, plans, and audits all read from the same record. Full guide: https://skillsdb.com/blog/skills-competencies-similar-but-different ### Competency Framework URL: https://skillsdb.com/learn/competency-framework A competency framework is the shared structure, spanning every job family, that names the competencies each one requires, levels them on a shared proficiency scale, and states the required level for every role, so that assessment, gap analysis, and development all read from one definition of good. A competency framework is the reference architecture for how an organization describes capable work. It holds the competencies, grouped by job family and often by a small set shared across all roles; the proficiency scale and the behavioral anchors that give each level a meaning; and the required level of each competency for each role. The framework itself does not record what anyone can do. It records what the work demands, and it is the fixed side of every gap calculation. Assessments supply the moving side. A framework earns its keep when three things are true: practitioners recognize their own work in the definitions, an assessor can place a person at a level without guessing, and a change in the framework flows automatically into the gap reports and plans built on it. A framework that fails any of the three becomes a document rather than a system. Full guide: https://skillsdb.com/blog/competency-models-4-creation-methods-how-well-they-perform ### Skills Matrix URL: https://skillsdb.com/learn/skills-matrix A skills matrix places people on one axis and skills on the other, recording, at each intersection, the proficiency level the person has demonstrated, so that a manager can see coverage, gaps, and depth for a team at a glance. A skills matrix is a view over a skills inventory. The inventory holds one record per person per skill, with a level, a date, and a method; the matrix arranges those records into a grid so that patterns become visible: a column with no 3s is a skill nobody can perform independently, a row full of 4s is a person who is probably the single point of failure, a team whose required levels are met only by one shift is a scheduling risk. The matrix itself stores nothing new. Its value comes from the records underneath being assessed rather than self-declared, dated rather than assumed current, and scored on the same anchored scale across every skill. Matrices are read most often by managers and resource planners deciding who can be assigned, who needs backup, and where the next development effort should go. The layout changes with the question being asked; the underlying record does not. Full guide: https://skillsdb.com/blog/skills-matrix-complete-guide ### Training Matrix URL: https://skillsdb.com/learn/training-matrix A training matrix maps each person to the training their role requires and records, per requirement, whether it has been completed, the date it was completed, and when it expires, so that coverage and currency can be read for a team, a site, or an audit. A training matrix tracks obligations rather than abilities. Each role carries a set of required training items: procedures, certifications, refreshers, revision-specific briefings. Each person in the role is mapped to those items, and every cell holds a status derived from a trained date and, where the item is perishable, an expiry. The matrix answers a compliance question, "is everyone who must be trained on this trained, on the current revision, within the validity window?", and a scheduling question, "who is about to lapse?" It does not say how well anyone performs; that is the skills matrix's job. In regulated operations the two grids are kept deliberately separate and cross-referenced, because an auditor asks for both: proof that training occurred and proof that competence was verified. A matrix that stores only checkmarks, without dates and revisions, cannot answer either question once the procedure changes. Full guide: https://skillsdb.com/blog/training-matrix-how-to-build ### Employee Development Plan URL: https://skillsdb.com/learn/development-plan A development plan is a dated commitment that names one or more assessed proficiency gaps, states the target level for each, assigns the learning and experience that will close them, and defines the evidence that will show the new level has been reached. A development plan is the operational link between a gap and its closure. It starts from an assessment, not an aspiration: the person holds level 2 on a competency the current or next role requires at level 3. The plan then commits to a target level, a set of actions with owners and dates, and a form of evidence that will be accepted as proof, followed by a reassessment that records the new level. Plans typically run 6 to 12 months and carry two to four priority gaps; more than that dilutes effort and is rarely completed. A competency development plan is the variant anchored to a role's competency framework, so that the target levels are the role's required levels rather than numbers chosen in a conversation. Plans that skip the evidence and reassessment steps become course lists, and course lists are why most development programs cannot show that anyone became more capable. Full guide: https://skillsdb.com/blog/competency-development-plan-all-you-need-to-know ### Career Pathway URL: https://skillsdb.com/learn/career-pathway A career pathway is a defined sequence of roles or levels, each with the skills, proficiency levels, and evidence a person must demonstrate to move to the next, so that progression is visible and testable rather than left to tenure or a manager's discretion. A career pathway makes movement inside an organization legible. A career ladder lists titles in order and leaves the criteria implied; a pathway states, for each step, the skills required, the level on each, and the evidence that satisfies it: an assessment, a certification, a training record with an expiry date. Four parts recur. The career or role is the container. Levels are the ordered steps within it, junior to principal, each carrying its own required levels for the same skills. Sections group the skills so a forty-skill role reads as six themes, not one list. Skills, with their required levels per step, are the criteria. Because the required levels come from the framework and the demonstrated levels come from assessment, the distance between where a person stands and the next step is a gap analysis, not a conversation. That is what makes a pathway honest: the same evidence that qualifies one person qualifies the next, and a person can see their own position without asking. Full guide: https://skillsdb.com/blog/skills-based-career-pathing ### Certification Tracking URL: https://skillsdb.com/learn/certification-tracking Certification tracking is the practice of recording, for every person and every credential their role requires, the issue date, the expiry date, the evidence behind it, and who approved it, so that an organization can show at any moment who is qualified, who is lapsing, and who never was. Certification tracking answers a narrower question than a skills matrix does. It does not ask how well someone performs; it asks whether a third party has attested that they may perform at all, and whether that attestation is still in force. A forklift license, a Part 145 authorization, a data center electrical safety card, a nursing license: each has an issuer, an issue date, a credential number, and usually an expiry. Tracking means holding those fields per person, attaching the certificate itself as evidence, and routing the record through an approval so that the entry is verified rather than self-declared. The hard part is not the first entry but the renewal cycle. Credentials expire on different clocks, renewals need lead time, and a lapsed certification on a live shift is a compliance finding in manufacturing, aviation, healthcare, and any site an insurer inspects. Tracking exists so that the lapse is visible thirty days before it happens, not the morning after. Full guide: https://skillsdb.com/blog/employee-training-tracking-software ### Learning Plan URL: https://skillsdb.com/learn/learning-plan A learning plan is the set of learning resources assigned to or chosen by one person, each linked to a skill and tracked through to completion, that carries out the commitments made in their development plan. A learning plan is the working queue of a person's development. Where a development plan states the gap, the target level, the deadline, and the evidence, the learning plan holds the resources that will get there: the course, the shadowing assignment, the internal workshop, the book. Items arrive three ways: a manager or administrator assigns them, the person's career links them, or the person adds them from the library or as a custom entry. Each item moves through four stages, To Do, In Progress, Completed, and Archived, and each shows who added it and when, so the plan is also a record of who recommended what. The plan is personal but not private; managers see their reports' plans, add to them, and log hours and percent complete. A team-level view lists every person and resource in one table so a manager can see who has not started. What the plan cannot do is close a gap. Completion is activity; the level changes when the skill is reassessed. Full guide: https://skillsdb.com/blog/create-employee-development-plans ### Promotion Workflow URL: https://skillsdb.com/learn/promotion-workflow A promotion workflow is the defined sequence an organization follows from evidence that a person meets the next level's requirements, through the approvals that confirm it, to the recorded change of role or level. A promotion workflow replaces the conversation-and-spreadsheet route to advancement with a sequence anyone can inspect. It starts with criteria that are written down: the benchmark level the next career level requires for each skill, the training the target role requires, the certifications that must be current. It continues with evidence against those criteria: assessed grades in the skills matrix filtered to the next level, approved training records, a manager's judgment. It ends with approvals from the people accountable for the decision and a level or career change recorded with a date. The value is in the order and the record. When the steps run in sequence and each one is logged, an employee can see what advancement requires, a manager can see who is close, and HR can answer the question that follows every contested promotion: on what basis, approved by whom, and when. Without the sequence, promotion criteria live in the memory of whoever made the last decision. Full guide: https://skillsdb.com/blog/skills-based-career-pathing ### Skills-Based Organization URL: https://skillsdb.com/learn/skills-based-organization A skills-based organization is one that uses skills, assessed and kept current, as the unit for deciding who does what work, who is hired, who is developed, and who moves, instead of relying on job titles, tenure, and the org chart. Most organizations run on proxies. A title stands in for what a person can do, tenure stands in for how well, and the org chart decides who can be considered for what. A skills-based organization replaces the proxies with the thing itself: a skills library in its own language, an inventory of who holds which skills at which assessed level, and role profiles that state what each role requires. Once those three exist, decisions that used to run on judgment can run on comparison. Staffing becomes a search for people at level 3 or above in the skills the project needs. Hiring starts from the gaps the inventory cannot fill. Development targets a named skill to a named level. Mobility becomes visible, because a person in one function can be measured against a role in another. The model is not a reorganization. It is a change in what counts as evidence, and it is adopted one job family at a time. Full guide: https://skillsdb.com/blog/skills-based-organization ### Skills Gap Analysis URL: https://skillsdb.com/learn/skills-gap-analysis A skills gap analysis compares the proficiency level a role requires for each skill against the level a person has demonstrated, and reports the difference so that development, hiring, and staffing decisions rest on a measured shortfall rather than an impression. A skills gap analysis is arithmetic on two records: a required level and an assessed level for the same skill and the same person. The required level, often called a benchmark, comes from the role and the person's level within it; a junior may need a 2 where a senior must reach a 4. The assessed level comes from a dated assessment, self, manager, or practical. When the assessed level sits below the benchmark, a gap exists; when it meets or exceeds it, there is none. Everything else is aggregation: the same subtraction run across a team becomes a coverage view, across a site becomes a risk register, across the organization becomes a workforce plan. The discipline lies in what feeds the subtraction. An analysis built on self-declared levels or on benchmarks nobody owns produces gaps that look precise and mean nothing. A skill with no recorded assessment is unassessed, not a gap, and should be reported as such. Full guide: https://skillsdb.com/blog/skills-gap-analysis-complete-guide ### Skills Matrix vs. Training Matrix URL: https://skillsdb.com/learn/skills-matrix-vs-training-matrix A skills matrix records how well each person performs each skill as an assessed proficiency level; a training matrix records whether and when each person completed the training a skill requires, and whether that training is still current. The two grids share their axes and their data source and answer different questions. In a skills matrix every cell is an assessed level on the organization's scale, colored against the role's benchmark, so a team lead can see who can do the work and who is a single point of failure. In a training matrix every cell is a trained date with a status computed from it: approved, pending, expiring, expired, or N/A where the skill is not assigned. The first grid is read for capability and staffing; the second for compliance and currency. They stay separate because completion does not prove competence and competence does not prove the paperwork is in date, and an auditor asks for both. What ties them together is the person-to-skill record underneath: one skill carries both an assessed grade and a trained date, so a change to either appears in its grid without a second entry. Full guide: https://skillsdb.com/blog/skills-matrix-complete-guide ### Skills Survey URL: https://skillsdb.com/learn/skills-survey A skills survey is a question-based instrument that asks people to report on their skills, interests, certifications, or experience, producing structured self-reported data that seeds an inventory or captures context an assessment cannot. A skills survey collects what people say about themselves. It asks a targeted population a fixed set of questions, from multiple choice and Likert scales to short text, certification details, and file uploads, and stores every answer against the respondent's identity. That makes it the right instrument for intake and context: which skills a new hire believes they bring, who is interested in a rotation, which certifications exist that nobody recorded, how a team feels about the training it received. It is the wrong instrument for proficiency. A survey answer is a claim, not an observed or tested level, so a claimed 4 belongs in the inventory as a hypothesis that a manager or practical assessment later confirms. The distinction matters because survey data is cheap to collect and easy to over-trust. Used for seeding, discovery, and follow-up, it accelerates everything downstream; used as evidence, it puts unverified opinions in the skills matrix. Full guide: https://skillsdb.com/blog/employee-surveys ### Skills Taxonomy URL: https://skillsdb.com/learn/skills-taxonomy A skills taxonomy is the controlled, organized vocabulary of skills an organization uses to describe work, grouped so that every role, assessment, and report draws from the same named list rather than from free text. A skills taxonomy answers one question before any other skills work can begin: what are the words? Without a controlled list, two managers describe the same capability three ways, a search for "welding" misses "MIG welding," and no two teams can be compared. The taxonomy fixes the names, attaches a definition to each, and groups them so that a library of several hundred skills stays navigable. Three layers do the work. The skill itself is the unit that gets assessed. Groupings, whether called categories, sections, or labels, collect related skills for browsing and reporting. Roles then draw the skills they require from the library, so the taxonomy and the job architecture stay connected rather than maintained twice. The recurring mistake is importing a large industry taxonomy and expecting adoption. Those lists look complete in a demo and stall in use because they describe work in someone else's language. Two hundred skills the organization named itself outperform ten thousand it never will. Full guide: https://skillsdb.com/blog/what-are-skills-types-and-skill-sets ### Succession Planning URL: https://skillsdb.com/learn/succession-planning Succession planning is the practice of identifying the roles an organization cannot leave vacant and preparing, in advance, the people who could fill them, measured by how closely each candidate's assessed skills match what the role requires. Succession planning answers a narrow question with a wide blast radius: if this role opened tomorrow, who could step in, and how far from ready are they? Traditional plans answer it with names on a slide, chosen by tenure, visibility, or a manager's instinct, and the plan is rarely tested until the day it is needed. A skills-based plan treats readiness as a measurement. The critical role carries a profile of required skills and certifications at required proficiency levels; each candidate carries assessed levels for the same skills; the distance between the two is the readiness gap, and the development plan is whatever closes it. Ready-now means no gaps at the role's level. Ready-soon means gaps a dated plan can close. The same comparison surfaces people nobody nominated, because it starts from evidence rather than a list of favorites. Succession is therefore not a separate system but a use of the skills inventory, role profiles, and gap analysis that already exist. Full guide: https://skillsdb.com/blog/skills-based-succession-planning ### Upskilling and Reskilling URL: https://skillsdb.com/learn/upskilling-reskilling Upskilling raises a person's proficiency in a skill their current role already requires; reskilling builds proficiency in a skill for a role they do not yet hold, and both are complete only when a reassessment records the new level. Upskilling and reskilling describe two directions of development that are often run as one program and measured as neither. Upskilling is vertical: the maintenance technician at level 2 on PLC troubleshooting reaches level 4 because the line now runs on a newer controller. Reskilling is lateral: the same technician learns data center cooling systems because the plant is closing and the operator across town is hiring. The distinction matters because the starting point, the owner, and the success measure differ. Upskilling starts from a gap against the current role's required level and is owned by the manager. Reskilling starts from a gap against a target role and is owned jointly by the person and whoever runs internal mobility. Both fail the same way: a catalog of courses is assigned, completions are counted, and nobody checks whether anyone can do the thing. The sequence that works is assess, name the gap, attach a resource to that gap, and reassess. Full guide: https://skillsdb.com/blog/upskilling-2025-future-of-work ### Workforce Planning URL: https://skillsdb.com/learn/workforce-planning Workforce planning is the discipline of comparing the capability an organization has against the capability its strategy will require, by role, location, and time, and deciding how to close the difference by building, buying, borrowing, or redeploying. Workforce planning began as headcount arithmetic: how many people, in which jobs, at what cost, next year. That version still runs in most finance and HR teams, and it fails at the moment it matters, because a headcount says nothing about whether the people counted can do the work the plan assumes. Skills-based workforce planning changes the unit from positions to capabilities. Demand is expressed as roles with required skills at required levels, multiplied by how many of each role a site, shift, or initiative needs. Supply is the assessed inventory: who holds those skills today, at what level, and where. The plan is the difference, read across the organization's own dimensions, and each shortfall gets a decision: develop the people who are close, hire where nobody is, redeploy where a skill is deep in one place and absent in another. The plan is only as good as the inventory beneath it, which is why assessment comes first. Full guide: https://skillsdb.com/blog/workforce-planning-with-skills-data ## Use Cases ### Talent Development URL: https://skillsdb.com/use-cases/talent-development Build talent development programs on verified skills data — not guesswork. SkillsDB connects every learning plan, assessment, and career conversation to assessed proficiency so development closes real gaps instead of checking boxes. Gap analysis shows exactly where people need to grow. Learning plans target specific competency gaps. Managers and employees see progress over time. ### Workforce Strategy URL: https://skillsdb.com/use-cases/workforce-strategy Plan headcount, model future skill needs, and align talent investments to business goals using real-time skills data. SkillsDB provides the workforce intelligence layer that strategy requires — assessed proficiency across the org, gap analysis by team and function, and the ability to model scenarios based on actual capability, not assumptions. ### Resource Planning URL: https://skillsdb.com/use-cases/resource-planning Staff projects and optimize bench time using verified, real-time skills data. Search for people by skill, certification, and proficiency level. Match the right people to the right projects based on assessed capability, not outdated resumes or manager memory. Reduce bench time and improve utilization. ### Frontline Training URL: https://skillsdb.com/use-cases/frontline-training Rapid onboarding, compliance tracking, and competency verification for frontline and operational teams. Track certifications with expiry alerts. Verify skill readiness across locations. Prove workforce readiness to operations leadership with real data instead of training completion reports. ### Career Pathways URL: https://skillsdb.com/use-cases/career-pathways Visible, skill-based progression paths that drive retention and internal mobility. Every career level has defined skill requirements and proficiency benchmarks. Employees see exactly where they stand and what their next level requires. Managers have objective criteria for promotion conversations. ### Succession Planning URL: https://skillsdb.com/use-cases/succession-planning Identify ready-now and ready-soon talent for critical roles using verified skills data. Proficiency assessments measure where successor candidates stand. Gap analysis shows exactly what development is needed. When a critical role opens, you already know who's ready. ### AI Transformation URL: https://skillsdb.com/use-cases/ai-transformation Map AI-readiness across the workforce, identify reskilling priorities, and track adoption of AI skills. Assess AI-relevant competencies — data literacy, prompt engineering, automation design — against verified proficiency data. See where AI readiness already exists and where investment will have the highest return. ### Partner Certifications URL: https://skillsdb.com/use-cases/partner-certifications Track and verify partner and channel credentials across external teams. Manage the full certification lifecycle from assignment through renewal. Automated expiry alerts prevent revenue-impacting compliance gaps. Real-time dashboards show certification coverage and risk. --- ## Perspectives SkillsDB publishes in-depth perspective pieces on key workforce challenges — the philosophy behind the platform. ### Perspective on Talent Development URL: https://skillsdb.com/perspective/talent-development Organizations have spent a decade buying training content. Most still can't tell you whether their people are more skilled than they were five years ago. The problem isn't training spend — it's the absence of a feedback loop between development and measured proficiency. ### Perspective on Workforce Strategy URL: https://skillsdb.com/perspective/workforce-strategy Every workforce plan has a hidden assumption: that the right headcount, in the right roles, will produce the capability the strategy requires. Without skills data, that assumption is untested. ### Perspective on Resource Planning URL: https://skillsdb.com/perspective/resource-planning In most organizations, the most consequential resourcing decisions are made based on who people know, not what people know. That's a solvable problem when skills are visible and verified. ### Perspective on Frontline Training URL: https://skillsdb.com/perspective/frontline-training Training completions tell you that someone watched the video. They don't tell you that someone can do the job safely, correctly, and without supervision. The gap between "trained" and "competent" is where risk lives. ### Perspective on Career Pathways URL: https://skillsdb.com/perspective/career-pathways Most organizations have career ladders. Very few have career paths. When employees can't see what skills their next level requires — or where they stand — they leave. Career clarity is the new retention strategy. ### Perspective on Succession Planning URL: https://skillsdb.com/perspective/succession-planning Most succession plans are built on tenure, visibility, and gut feel — not verified skills data. When the moment comes, they fall apart. Skills-based succession planning makes every decision defensible. ### Perspective on AI Transformation URL: https://skillsdb.com/perspective/ai-transformation Every organization wants to upskill for AI. Almost none know what skills their workforce already has. Without a baseline, AI training is an expensive guess. You need to measure before you can develop. ### Perspective on Partner Certifications URL: https://skillsdb.com/perspective/partner-certifications Partner certifications aren't optional — they're contractual obligations tied to revenue. Most organizations still manage them in spreadsheets. One missed renewal can cost a partnership tier. --- ## Features ### Skills Matrix URL: https://skillsdb.com/features/skills-matrix Interactive visual matrix mapping every employee against every required skill. Color-coded proficiency grades (green = meets benchmark, red = below, gray = ungraded). Filterable by team, role, skill, and career level. Toggle between self-assessment and manager grades. Export to Excel. ### Gap Analysis URL: https://skillsdb.com/features/gap-analysis Real-time skill gap visualization with radar charts and benchmark comparisons. Surface the exact gaps between where people are and where they need to be. Prioritize development investments based on actual proficiency data. ### Proficiency Assessment URL: https://skillsdb.com/features/proficiency-assessment Structured assessment with configurable grading scales. Capture employee grades, manager grades, and benchmarks. Track how proficiency moves over time. Compare self-assessment against manager evaluation to surface blind spots. ### Career Frameworks URL: https://skillsdb.com/features/career-frameworks Skill-based career pathways with visible progression requirements at each level. Employees see exactly where they stand. Managers have objective criteria for promotions. Leadership sees bench strength across the organization. ### Competency Frameworks URL: https://skillsdb.com/features/competency-frameworks Build competency frameworks in your organization's language. No locked taxonomies or rigid hierarchies. Define skills, proficiency levels, and benchmarks mapped to your roles and culture. ### Skills Library URL: https://skillsdb.com/features/skills-library Centralized skills taxonomy management. Create and organize skills that connect to assessments, career frameworks, learning plans, and gap analysis. Every skill in the library is a living data point, not a static label. ### Learning Plans URL: https://skillsdb.com/features/learning-plans Development plans tied to specific assessed skill gaps. Every learning resource connects to a specific competency target. Employees see why a resource matters. Managers track completion against actual proficiency benchmarks. ### Certifications URL: https://skillsdb.com/features/certifications Full certification lifecycle management — assignment, tracking, approval, expiration alerts, and compliance audits. Track credentials across the workforce with automated renewal reminders. ### Surveys URL: https://skillsdb.com/features/surveys Employee surveys with skill-updating question types. Collect data that feeds directly into skills profiles, proficiency grades, and gap analysis. ### Skill Flags URL: https://skillsdb.com/features/skill-flags Expert, Mentor, Trainer, and custom designations. Flag your top talent and subject matter experts. Search and filter by flags across the entire organization. ### Manager Analytics URL: https://skillsdb.com/features/manager-analytics Team skills dashboards showing proficiency distribution, gap concentrations, and development progress. Managers see where their teams stand and where to invest. ### Succession Planning Feature URL: https://skillsdb.com/features/succession-planning Data-driven succession planning powered by assessed proficiency. Identify ready-now talent, track readiness development, and make succession decisions based on verified skills data. ### Workforce Strategy Feature URL: https://skillsdb.com/features/workforce-strategy Workforce planning powered by real-time skills supply data. Model future capability needs against current assessed proficiency. --- ## Comparisons & Alternatives ### SkillsDB vs Cornerstone OnDemand Cornerstone OnDemand is primarily a learning management system that starts with content delivery and adds skills features on top. SkillsDB is a skills intelligence platform built from the ground up for skills assessment, gap analysis, and development. The key difference is foundational: Cornerstone is content-first (skills are a metadata layer on a content library), while SkillsDB is skills-first (assess proficiency, identify gaps, then connect to relevant learning). SkillsDB offers structured manager and self-assessment with benchmarks, interactive skills matrix, career pathways with visible requirements, and real-time gap visualization with radar charts. Cornerstone excels at content delivery and compliance training at scale. URL: https://skillsdb.com/compare/skillsdb-vs-cornerstone ### SkillsDB vs Workday Skills Cloud Workday Skills Cloud uses machine learning to infer skills from HCM data. SkillsDB provides structured proficiency assessment with manager and employee grading against defined benchmarks. The difference: Workday tells you what skills might exist based on inference; SkillsDB measures them through assessment and tracks development over time. SkillsDB deploys in weeks without requiring a Workday implementation project. Both can work together — SkillsDB as the active skills engagement layer, Workday for broader HR processes. URL: https://skillsdb.com/compare/skillsdb-vs-workday ### SkillsDB vs SAP SuccessFactors SAP SuccessFactors is a comprehensive HCM suite covering the full HR lifecycle. SkillsDB is a purpose-built skills intelligence platform. While SuccessFactors has skills-related features across its modules, SkillsDB provides deeper skills assessment, gap analysis with radar charts, career pathway mapping, and development tracking — the active skills engagement layer that HCM suites don't provide. SkillsDB works alongside SAP SuccessFactors, not instead of it. URL: https://skillsdb.com/compare/skillsdb-vs-sap-successfactors ### SkillsDB vs Gloat Gloat is an internal talent marketplace that matches employees to opportunities using AI-inferred skills. SkillsDB is a skills intelligence platform that assesses what skills people actually have, identifies gaps, and builds development programs. A talent marketplace is only as good as its skills data — SkillsDB provides the assessed proficiency foundation that makes marketplace matching accurate. SkillsDB measures skills through structured assessment (manager grades, self-assessment, benchmarks); Gloat infers skills from profiles and activity. URL: https://skillsdb.com/compare/skillsdb-vs-gloat ### SkillsDB vs iMocha iMocha is a skills assessment platform with a large library of pre-built tests for hiring and internal benchmarking. SkillsDB covers the full skills lifecycle: assessment, gap analysis, career pathway mapping, learning plan integration, certification tracking, and development measurement. iMocha excels at pre-built technical skills testing; SkillsDB focuses on organizational competency assessment with configurable grading scales that map to your career frameworks. URL: https://skillsdb.com/compare/skillsdb-vs-imocha ### SkillsDB vs Fuel50 Fuel50 is a career experience and talent marketplace platform with AI-driven career pathing and opportunity matching. SkillsDB provides the assessed skills foundation — proficiency grading, gap analysis, competency frameworks — that makes career pathways credible. Fuel50 relies on self-reported skill levels and AI inference; SkillsDB uses structured assessment with manager and self-evaluation against benchmarks. URL: https://skillsdb.com/compare/skillsdb-vs-fuel50 ### SkillsDB vs Beamery Beamery is a talent lifecycle management platform spanning recruiting through internal mobility with AI-powered skills architecture. SkillsDB focuses entirely on your existing workforce — assessing proficiency, analyzing gaps, building career frameworks, and tracking development. Beamery starts from talent acquisition; SkillsDB starts from the skills of the people you already have. URL: https://skillsdb.com/compare/skillsdb-vs-beamery ### SkillsDB vs 365Talents 365Talents uses AI and NLP to automatically infer skills from employee data and match people to opportunities. SkillsDB provides structured skills assessment — manager and self-assessments with configurable grading and benchmarks. AI-inferred skills profiles are probabilistic; SkillsDB's assessed proficiency data is verified. Both approaches have value, but for development decisions and career planning, verified data matters. URL: https://skillsdb.com/compare/skillsdb-vs-365talents ### SkillsDB vs Kahuna Kahuna specializes in operational workforce compliance — skills verification, certification tracking, and deployment readiness for field teams in regulated industries. SkillsDB is a broader skills intelligence platform covering the full organization: assessment, gap analysis, career pathways, learning plans, and workforce strategy. Kahuna is operational and compliance-focused; SkillsDB is strategic and development-focused. URL: https://skillsdb.com/compare/skillsdb-vs-kahuna ### SkillsDB vs TechWolf TechWolf is a skills AI engine that integrates with existing HR systems (Workday, SAP, Oracle) to extract and standardize skills data. SkillsDB is where skills are actively assessed, gaps are made visible, and development happens. TechWolf is a data layer that powers other tools; SkillsDB is the operating system where employees, managers, and L&D teams interact with skills daily. URL: https://skillsdb.com/compare/skillsdb-vs-techwolf ### SkillsDB vs SkyHive SkyHive (now part of Cornerstone) provides external labor market intelligence — future skills demand, reskilling pathways based on market trends. SkillsDB provides internal workforce intelligence — assessed proficiency, gap analysis, career pathways, and development tracking for your actual employees. External market data tells you where to head; SkillsDB tells you where you are now and how to get there. URL: https://skillsdb.com/compare/skillsdb-vs-skyhive ### SkillsDB vs AG5 AG5 is a competency matrix tool for frontline operations, focused on qualification status: who is trained and in date for a task. SkillsDB is a skills intelligence platform that measures assessed proficiency against what each role requires, then turns gaps into development plans, career pathways, and staffing decisions. AG5 answers "who is qualified"; SkillsDB answers "who is capable, and what closes the gap." SOC 2 Type II (independently audited), GDPR compliant, SSO, SCIM, full GraphQL API. Skills and competency management since 2008; manufacturing customers include Denso, Grammer, and Toro. URL: https://skillsdb.com/compare/skillsdb-vs-ag5 ### SkillsDB vs Degreed Degreed is a learning experience platform (LXP) that aggregates learning content from multiple sources with AI-powered recommendations. SkillsDB is a skills intelligence platform that assesses proficiency, analyzes gaps, maps career pathways, and connects development to verified competency data. Degreed starts with content and infers skills; SkillsDB starts with skills and connects to relevant learning. Course completion doesn't mean competency — SkillsDB measures whether development actually works. URL: https://skillsdb.com/compare/skillsdb-vs-degreed ### SkillsDB vs Rippling Rippling is an all-in-one workforce management platform unifying HR, IT, and Finance — payroll, benefits, device management, app provisioning, and workforce planning. SkillsDB is a purpose-built skills intelligence platform. Rippling manages HR operations and knows who your employees are; SkillsDB manages skills and knows what they can do. Rippling offers performance reviews and an LMS module, but lacks structured skills assessment, competency frameworks, gap analysis, career pathways, or skills matrix capabilities. SkillsDB provides all of these and works alongside Rippling via API, SSO, and SCIM. URL: https://skillsdb.com/compare/skillsdb-vs-rippling ### SkillsDB vs SuccessionHR SuccessionHR is a dedicated succession planning tool managing key roles, successor candidates, readiness assessments, talent grids, and handover plans. SkillsDB is a skills intelligence platform providing the assessed skills foundation across your entire organization. Succession planning is downstream of skills intelligence — you can't identify the right successor without knowing what skills the role requires and what skills candidates actually have. SkillsDB provides assessed proficiency, gap analysis, and development tracking that makes succession decisions data-driven rather than aspirational. URL: https://skillsdb.com/compare/skillsdb-vs-successionhr ### SkillsDB vs Lightcast Lightcast (formerly Emsi Burning Glass) is the global standard in labor market intelligence, aggregating data from 2.5 billion job postings, 800 million career profiles, and 100+ government sources across 160+ countries. SkillsDB provides internal workforce intelligence — assessed proficiency, gap analysis, career pathways, and development tracking for your actual employees. Lightcast tells you what the market demands; SkillsDB tells you what your people have. They are powerfully complementary: Lightcast provides the "where should we be heading" data, SkillsDB provides the "where are we now" assessment. URL: https://skillsdb.com/compare/skillsdb-vs-lightcast ### LMS vs Skills Intelligence Platform A comprehensive comparison of why content-first LMS platforms (Cornerstone, Docebo, Degreed) fall short for skills management. LMS platforms were built for content delivery — when they add skills features, it's a layer on top of a content-first data model. Skills intelligence platforms like SkillsDB start from skills assessment as the foundation. This page compares the two approaches across 10 dimensions including skills data source, gap analysis, career pathways, and proof of development. URL: https://skillsdb.com/compare/lms-vs-skills-platform ### Talent Marketplace vs Skills Intelligence Platform Compares talent marketplace platforms (Gloat, Fuel50, Beamery) with skills intelligence platforms. Talent marketplaces match people to opportunities using AI-inferred skills. Skills intelligence platforms assess what skills people actually have. The key insight: a marketplace is only as good as its skills data. SkillsDB provides the assessed proficiency foundation that makes marketplace matching accurate. URL: https://skillsdb.com/compare/talent-marketplace-vs-skills-platform ### SkillsDB vs Docebo URL: https://skillsdb.com/compare/skillsdb-vs-docebo Docebo is an AI-powered learning management system with content authoring, social learning, and a content marketplace. SkillsDB is a skills intelligence platform that tells you what skills to develop and whether the training worked — so L&D investment targets real gaps. Docebo delivers learning content; SkillsDB provides the diagnosis before content, proof that training worked, and works alongside Docebo as complementary systems. Comparison covers 12 dimensions including skills-first methodology, competency frameworks, proficiency assessment, gap analysis, interactive skills matrix, career pathways, learning content, and certification tracking. ### SkillsDB vs Skills Base URL: https://skillsdb.com/compare/skillsdb-vs-skills-base Skills Base is a lightweight skills tracking and visualization tool. SkillsDB turns skills data into career frameworks, gap analysis, development plans, and workforce strategy — the full intelligence layer. Skills Base tracks skills; SkillsDB provides intelligence, not just inventory. Comparison covers career frameworks that drive growth and manager-validated proficiency. Migration from Skills Base to SkillsDB is supported. ### SkillsDB vs MuchSkills URL: https://skillsdb.com/compare/skillsdb-vs-muchskills MuchSkills is a Sweden-based visual skills mapping platform with a skills matrix, skills-based org chart, certification tracking, gap reports, and skills-based resourcing popular with consultancies. SkillsDB is a skills intelligence platform that assesses proficiency against role benchmarks with manager and self-assessment, then connects that record to gap analysis, development plans, career frameworks, and certification tracking. MuchSkills makes skills visible; SkillsDB makes them defensible and actionable. SOC2 Type II certified, GDPR compliant, SSO, SCIM, and a full GraphQL API. Comparison covers 12 dimensions, who should choose which, migration, and evaluation questions. ### Best Skills Management Software 2026 A comprehensive comparison of skills management platforms including SkillsDB, Cornerstone OnDemand, Workday Skills Cloud, Gloat, iMocha, 365Talents, and AG5. Compares across 10 dimensions: skills data source, competency frameworks, gap analysis, career pathways, skills matrix, learning plans, certification tracking, enterprise security, language support, and time to value. SkillsDB is the only platform purpose-built for skills intelligence since 2008 with 18 years of expertise. URL: https://skillsdb.com/compare/best-skills-management-software --- ## Landing Pages ### Skills Matrix Software URL: https://skillsdb.com/lp/skills-matrix Map proficiency, spot gaps, and make talent decisions with confidence — all in one interactive skills matrix. Key capabilities: Color-coded proficiency mapping, manager vs. self grades, benchmark comparison, skill flags, six visualization types, one-click Excel export. Trusted by Fortune 500 teams. ### Certification Tracking Software URL: https://skillsdb.com/lp/certifications Track every credential, expiry date, and approval in one system — with structured workflows, renewal history, and audit-ready reporting. Key capabilities: Full lifecycle tracking, expiration monitoring, structured approvals, team & org visibility, document management, renewal history. ### Skills-Based Organization Software URL: https://skillsdb.com/lp/skills-based-organizations Build a skills-based organization with verified proficiency data, career frameworks, and workforce intelligence — not job titles. Skills-based organizations are 63% more likely to achieve results and 98% more likely to retain high performers (Deloitte). Key capabilities: Skills intelligence, career frameworks, gap analysis, resource planning, learning plans, workforce strategy. ### Training Matrix Software URL: https://skillsdb.com/lp/training-matrix Track skill-based training completion across your workforce with structured approvals, expiration tracking, and audit-ready evidence. Key capabilities: Evidence-based submission, manager & SME approval, training expiration tracking, training matrix view, configurable per skill, connected to proficiency data. ### Competency Matrix Software URL: https://skillsdb.com/lp/competency-matrix Build and manage competency matrices that connect proficiency levels to role requirements. Track competencies across your entire workforce. Key capabilities: Role-based competency profiles, color-coded proficiency matrix, manager & self assessments, competency frameworks, gap analysis, export & reporting. ### Skills Gap Analysis Software URL: https://skillsdb.com/lp/skills-gap-analysis Identify skill gaps across your workforce automatically. Compare current proficiency against role benchmarks and prioritize development where it matters. Key capabilities: Automatic gap detection, gap prioritization, team & org-level views, manager vs. self gaps, training connection, benchmark comparison charts. --- ## Trust, Privacy & AI ### AI Policy URL: https://skillsdb.com/ai-policy How SkillsDB uses artificial intelligence. Across the product AI does five kinds of things: drafts structured content, extracts meaning from documents and free text, compares something against a standard, summarizes patterns across records, and suggests what might come next. Data handling commitments: SkillsDB does not use customer data to train or improve models made available to any other customer, and contractually requires its model providers not to train on it. Customer data is never pooled — it is not used to generate output, benchmarks, or comparisons for another customer. Market and comparative information comes from publicly available sources, licensed third-party data, and the general knowledge of the underlying models. Customers own the output generated for them. AI inputs are currently processed in the United States. Intermediate artifacts such as vector representations and indexes exist only to serve that customer and are deleted or rendered permanently non-attributable on termination. Human oversight: SkillsDB does not act as an agent of the customer and does not perform employment functions on their behalf. AI features are not designed to make autonomous employment, compensation, or promotion decisions. For any decision with legal or similarly significant effects on an individual, a human being makes, reviews, or oversees it. SkillsDB does not track how often customers accept or override a recommendation. Not supported: automated screening, scoring, ranking or rejection of individuals without human review; determining eligibility for employment, credit, housing or insurance; inferring protected characteristics; legal, compliance or professional advice. Model providers are subprocessors and the authoritative list is published at https://trust.skillsdb.com/subprocessors ### Privacy Policy URL: https://skillsdb.com/privacy How SkillsDB collects, uses, shares, and retains personal data. Covers GDPR legal bases, automated decision-making and profiling, subprocessors, retention periods, security practices, breach notification, international transfers under Standard Contractual Clauses, and rights under GDPR, UK GDPR, CCPA/CPRA and other US state privacy laws. ### Terms of Service URL: https://skillsdb.com/terms Governs self-serve subscriptions and free workspaces. Includes an Artificial Intelligence Features section covering output ownership, the probabilistic nature of AI output, human decision-making responsibility, no training on customer data, processing of input, model providers as subprocessors, exclusion of AI features from the SLA, and the regenerate remedy for third-party output claims. Customers with a signed Software Services Agreement are governed by that agreement instead. ### Data Processing Addendum URL: https://skillsdb.com/dpa GDPR Article 28 processor terms, Standard Contractual Clauses for EU, UK and Swiss transfers, subprocessor obligations, and security measures. ### Service Level Agreement URL: https://skillsdb.com/sla Availability commitment, support coverage, and service credits for paid tiers. AI features are excluded from the availability commitment. ### Trust Center URL: https://trust.skillsdb.com SOC 2 Type II report, security artifacts, and the authoritative subprocessor list. --- # Blog Posts ## Your First Competency Framework in 30 Days: A Week-by-Week Plan URL: https://skillsdb.com/blog/first-competency-framework-30-day-plan Every skills initiative starts with the same question: what skills actually matter here? Not the generic list from an HRIS vendor. The specific, measurable capabilities that define what good looks like in your organization, and what separates "meeting expectations" from "ready for the next level." The answer lives in a competency framework. The definition, the four build methods, and a worked example are in Competency Framework: How to Build One . This article is the other half: the project plan for the person who has to run it. Because the framework itself is the easy part. The real work is political, not technical. You are making explicit what was previously assumed, and assumptions, once surfaced, start arguments. A 30-day plan gives those arguments a place to happen, a deadline, and a way to end. How Long Does It Take to Build a Competency Framework? A first competency framework for one job family of five to eight roles takes about 30 days from kickoff to first assessment results, and roughly 60 hours of people's time spread across a sponsor, a framework owner, four to six subject-matter experts, and the managers of the pilot group. Week one fixes scope and the people; week two drafts the competencies and the proficiency scale with the people who do the work; week three calibrates the drafts in workshops and settles the disagreements; week four sets required levels per role, runs the first assessments, and ships the framework to the pilot group. Organizations that try to cover every role at once take six to nine months and usually stall a third of the way through. Organizations that pilot one job family finish in a month and repeat the cycle for the next family in three weeks. The rest of this article is that month, week by week, with a data center operations job family as the running example: facilities technicians, shift leads, and a site operations manager across two sites. Before Day One: Decide These Five Things The 30 days start when these are written down, not when the kickoff meeting is booked. Purpose. Assessment and development, compliance evidence, promotion criteria, or hiring. One primary purpose; it sets the level of detail and decides who has to agree. Pilot job family. One family, five to eight roles, where the need is loudest. For the data center, operations: certification currency is an audit item and shift leads are promoted on instinct. Sponsor. A named executive who will sit in the week-three calibration session. If nobody senior will give you 90 minutes in week three, you do not have a sponsor. Framework owner. One person who runs the project and holds the pen. Usually L&D or talent. Not a committee. Where it will live. A spreadsheet is fine for the pilot. Decide now what it moves into afterward. Who Does What The framework is written by the people who know the work and owned by the person who maintains it. This table is the whole governance model for a pilot. Activity Sponsor Framework owner Subject-matter experts Managers of the pilot group L&D / talent Set purpose and scope Accountable Responsible Consulted Consulted Informed Draft competencies and anchors Informed Accountable Responsible Consulted Consulted Choose the proficiency scale Informed Responsible Consulted Consulted Accountable Calibration workshops Attends week 3 Facilitates Responsible Responsible Consulted Set required level per role Accountable Responsible Consulted Responsible Informed Run first assessments Informed Accountable Informed Responsible Responsible Own the framework after day 30 Informed Accountable Consulted Consulted Responsible Two things to notice. Experts draft; L&D facilitates and formats. And managers own calibration and assessment, because a framework they didn't help calibrate is one they will quietly ignore. Week 1: Scope, Sponsor, and the Pilot Roles Time budget: about 8 hours, half of it the framework owner's. Confirm the five decisions in writing, one page, circulated to everyone in the table. Then inventory the roles in the pilot family. Not titles, roles. The data center has eleven titles across two sites that collapse into three roles: facilities technician (two levels), shift lead, and site operations manager. Titles are cheap to create; roles are what the framework hangs off. Recruit four to six experts: two top performers, one manager, and one person who consumes the work, here the site operations manager who lives with a bad shift handover. Ask each for four hours over two weeks, and book the week-three workshops now, because that is the meeting that slips. Close the week by agreeing the proficiency scale: four or five levels, one scale for the whole framework, labels people will say out loud. The data center chose four: Foundational, Working, Advanced, Expert. How to anchor a scale is covered in proficiency levels ; week one only decides which scale, so week two's drafts all use it. Week 2: Draft With the People Who Do the Work Time budget: about 20 hours, mostly subject-matter experts in two-hour blocks. The framework owner runs three two-hour sessions with the experts. The first answers one question per role: what does someone in this role need to be great at, not just good? Write down everything, then cut to eight to twelve competencies for the family: three to five every role shares, three to seven that vary by role. Twelve is the ceiling. Past it the framework becomes an assessment burden managers avoid. The data center group landed on five shared competencies: critical systems operation, method-of-procedure execution, incident response, compliance and evidence, and people leadership, plus vendor coordination for shift leads and capacity planning for the site manager. The second and third sessions write the anchors: one observable sentence per competency per level. "Understands incident response" is not an anchor. "Recognizes alarm conditions and escalates within the defined thresholds without prompting" is. Each expert drafts the competencies closest to their own work, then swaps. The rule for writing a competency definition applies to every anchor: a verb, an object, an observable standard, no evaluative adjectives. By Friday there is a draft grid: competencies down the side, four levels across, an anchor in every cell. It will be wrong in places. That is what week three is for. Week 3: Calibrate, Argue, Settle Time budget: about 18 hours, including the sponsor's 90 minutes. Calibration means walking every competency and level past the managers who will apply it and asking two questions: do you agree with how this level is defined, and can you name someone on your team who is at it? If two managers can't agree on what Working looks like for incident response, the anchor is rewritten in the room. If neither can name anyone at Expert, the level describes a job that doesn't exist here and gets pulled down. Run two 90-minute sessions with managers and experts together, then a third with the sponsor present. The third is not a review. It is where the sponsor settles what the first two couldn't. There will be three disagreements, and they are political, not technical. The argument about who is already Expert Someone senior is about to assess at Advanced in a competency they believed they owned, and their manager will push to soften the anchor. Keep the anchor and reframe the result: the framework describes the role's bar, not the person's worth, and a gap at the top of a role is a development target, not a verdict. If the sponsor won't hold that line in week three, the framework will be bent to fit people for the rest of its life. The argument about whose language wins Two sites describe the same competency differently and each is certain theirs is correct. Ask which version an auditor or a new hire would understand without a translator, use that one, and record the other as an alias. One competency; two vocabulary entries. The argument about scope creep Halfway through calibration someone will point out that the maintenance team has almost the same competencies and should be included. They may be right. Write it down as the second pilot and refuse to change the first. The plan works because the scope is fixed; the moment it flexes, the deadline goes with it. End the week with the sponsor saying, in front of the managers, that this grid is the definition of good for these roles until the next revision. Week 4: Required Levels, First Assessments, Rollout Time budget: about 14 hours, mostly managers assessing. Monday, set the required level per role in each competency. Facilities technicians need Advanced in critical systems operation and Foundational in people leadership; the site manager needs the reverse. This is where the framework becomes useful: required minus actual is a gap, and a gap is a thing you can close. Tuesday and Wednesday, run the first assessments. Dual assessment works best: each person rates themselves against the anchors and their manager rates them independently, fifteen minutes each way. The distance between the two ratings is data in its own right; it shows where anchors are unclear and where a conversation is overdue. Which methods produce trustworthy data is covered in skills assessment methods and tools . Thursday, review the results with managers before anyone else sees them. Look for three things: self-ratings a full level above manager ratings, which means an ambiguous anchor; required levels nobody in the role meets, which means the bar or the anchor is wrong; and gaps clustered in one site, which means a training need, not a framework problem. Fix the anchors that need fixing. Don't touch the ones that just produced uncomfortable answers. Friday, roll out. Each person sees their assessed levels, the required levels for their role, the gaps, and the anchors for the next level. Managers get the team view; the sponsor gets the aggregate. Nobody gets a PDF. The framework goes into a system that keeps anchors, assessments, and gaps together, so the competency framework and the proficiency assessment results are never in two places. The Template The pilot runs perfectly well in a spreadsheet. Ours has four tabs: a competency worksheet with a column per level for anchors, a scale tab, a role expectations matrix, and a calibration checklist with the questions for each workshop. It is the structure large enterprises use, cut down to a one-family pilot. Download the template and week one's paperwork is done in an afternoon. What to Measure at Day 30, 60, and 90 Three checkpoints tell you whether the pilot worked. Day 30. The framework is signed off, every person in the pilot group has a completed dual assessment, and every manager has reviewed their team's gaps. Missing any of the three, the pilot is not done, whatever the calendar says. Day 60. Each person has at least one development action tied to a specific gap, and the anchors have been revised at least once from assessment results. A framework unchanged after 60 days wasn't examined. Day 90. One question for the sponsor: has a decision been made because of this framework that would otherwise have gone differently? A promotion, a training purchase, a staffing choice, an audit response. Yes means the framework is infrastructure and the second job family starts. No means it is a document, and the next pilot fixes the reason first. The Month Is the Method Most framework projects fail the same way: everything at once, generic language, no calibration, no connection to anything. The 30-day plan makes each failure structurally difficult. One job family forces scope. Experts writing anchors forces specific language. Week three forces calibration. Week four forces the connection to assessment. The framework that comes out is smaller than the one most organizations set out to build, and it is the one they use. FAQ How long does it take to build a competency framework for one job family? About 30 days from kickoff to first assessment results, with roughly 60 hours of combined effort across a sponsor, a framework owner, four to six experts, and the pilot managers. The second job family takes about three weeks, because the scale, template, and calibration habits already exist. Who should own a competency framework project? One named framework owner, usually in L&D or talent, runs the project and maintains the framework afterward. Experts draft, managers calibrate and assess, and an executive sponsor settles disagreements and signs off. Committees produce frameworks nobody maintains. How many roles should a first competency framework cover? Five to eight roles in a single job family: enough to make required-level differences visible, small enough to calibrate in two workshops. Attempting the whole organization first is the most common reason framework projects stall. What is the hardest part of implementing a competency framework? Calibration: getting managers to agree on what each level looks like in practice, and getting a sponsor to hold the definitions when a senior person assesses lower than expected. Drafting is technical and fast; calibration is political and decides whether the framework survives. Do we need software to build a competency framework? Not for the pilot; a four-tab spreadsheet is enough for one job family. Software matters when assessments, gaps, and development actions need to stay connected across several families and over time, which is usually right after the first pilot succeeds. How do you know if a competency framework is working? At day 90, ask whether a real decision was made because of it that would otherwise have gone differently: a promotion, a training investment, a staffing choice, an audit response. If it changed a decision, it is infrastructure. If it was only published, it is a document. --- ## How to Choose Competency Management Software (Buyer's Guide) URL: https://skillsdb.com/blog/how-to-choose-competency-management-software Most competency management systems are bought after an audit finding, not before one. The auditor asks to see evidence that the person who ran a critical procedure last Tuesday was competent against the current revision of that procedure. The training manager produces a completion record from the LMS, dated two years ago, against a revision that has since changed twice. The finding is written. The corrective action says "implement a competency management process." The search for software begins the following week. Quick reference: Competency Management Software — the short version of this post, with the one table that matters. That is a bad way to buy anything. The pressure favors whatever demos fastest, and the category is full of products that demo well and fail in the second year, when the spreadsheet exports start again because the tool could not answer the question the auditor actually asked. This guide is for the buyer who wants to choose once. It covers what the software has to do, in the order it has to do it, where the common alternatives break, and the questions that expose the difference before the contract is signed. What Competency Management Software Does Competency management software maintains a defensible record of who is competent to do what, at what level, based on which evidence, as of which date. It holds a competency framework that defines the skills and behaviors each role requires and the proficiency level expected; it records assessments of individuals against that framework using multiple methods such as supervised sign-off, testing, manager observation, and certification; it tracks proficiency and currency over time, including expiry and reassessment; it computes the gap between required and demonstrated competence at the individual, team, and site level; it generates a training or qualification matrix showing coverage; and it keeps an audit trail of every change. The distinction from a learning management system is the direction of proof: an LMS proves someone attended training, while competency management software proves someone can do the work. Who Needs It and Why Now Every organization manages competence somehow. The question is whether the current method survives contact with a regulator, a customer audit, or an incident investigation. Regulated manufacturing. ISO 9001 clause 7.2 requires organizations to determine the competence necessary for work affecting quality, ensure people are competent on the basis of education, training, or experience, and retain documented evidence of that competence. Auditors read "documented evidence" literally. A completion certificate is evidence of training, not of competence. Life sciences. GMP frameworks expect competence to be demonstrated and periodically reconfirmed, with records tied to the specific procedure revision in force. The revision link is the detail most systems miss. Aviation and energy. Qualification, currency, and recurrent training have been formal requirements for decades. The systems that hold them are often decades old too, and the pressure now is to modernize without losing the audit history. Data centers. Technicians execute procedures where a single error takes down customer infrastructure. Operators increasingly need to show enterprise customers, not just regulators, that the person on shift is qualified on the exact procedure they are running. Safety-critical operations generally. Anywhere the cost of an unqualified person doing the work is measured in injuries or outages, competence has to be provable, not assumed. The "why now" is that the burden of proof has moved. Auditors, customers, and insurers have stopped accepting training records as competence records. The gap between the two is where findings, and incidents, live. The Six Core Capabilities, in Order The order matters. Each capability depends on the one before it, and vendors that lead with the last one usually have not built the first. Competency framework The framework defines, for every role, which competencies are required and at what proficiency level. It has to be built in your organization's language, mapped to your roles, with behavioral anchors that describe what each level looks like on the floor. Off-the-shelf frameworks are a starting point at best; adoption depends on people recognizing their own work in the definitions. The four ways to build one, and how they perform, are covered in the competency models post . The software's job is to hold the framework as structured data, version it, and connect every downstream record to it. See competency frameworks for how that looks in practice. Assessment Competence is demonstrated, not declared. The system has to support several assessment methods on the same competency and keep them distinct: supervised practical sign-off by a named qualifier, written or practical tests, manager observation, peer review, and certification evidence. A record that cannot say how competence was established is a record an auditor will question. Proficiency and currency tracking The assessed level is stored against the required level, with the date, the method, and the assessor. Every record carries a reassess-by date driven by that competency's own interval, because a forklift qualification and a data-analysis skill do not decay at the same rate. The system surfaces what is approaching expiry without anyone remembering to check. Gap analysis Required minus demonstrated, computed inside the system at the person, role, team, and site level. This is where the training manager sees that the night shift has one qualified operator for a station that needs three, before the shift starts rather than after the incident. If gap analysis requires an export to a spreadsheet, the software is a database, not a management system. Training matrix The matrix is the operational view: people on one axis, competencies or procedures on the other, status in each cell. Qualified, in training, expiring, lapsed. It is what the shift lead reads and what the auditor asks to see first. It has to be generated live from the assessment records, never maintained by hand. How to structure one is covered in the training matrix post . Evidence and audit trail Every assessment record attaches its evidence: the signed practical checklist, the test result, the certificate with its expiry, the procedure revision it was assessed against. Every change to a record is logged with who, when, and the prior value. Certifications and their renewals are tracked as first-class records; see certifications . This is the capability that turns the other five into something you can hand to an auditor and walk away from. Where the Alternatives Break Four approaches compete with purpose-built software. Each works up to a point. Approach Works until How it breaks Spreadsheet matrix Roughly 50 people, one site, one owner No audit trail; evidence lives elsewhere; expiry tracking is manual; the matrix is accurate on the day it was last edited; the owner leaves LMS with skills tab Training completion is the only proof required Records attendance, not demonstrated competence; no practical sign-off; weak or absent proficiency levels; gap analysis missing; cannot link a record to a procedure revision HCM suite skills module Skills are a reporting attribute, not an operational record Generic taxonomy; single self-rating per skill; no evidence attachment; no training matrix; owned by HR, not operations; changes require IT Quality management system add-on Competence is a document, not a person-level record Tracks that a training document exists and was read; no proficiency, no gap, no matrix; strong on procedure control, weak on people Purpose-built competency management The organization needs proof of competence, not proof of training Requires a real framework definition effort up front; more to configure than a spreadsheet; the wrong choice for teams that only need attendance records The pattern in the table is that every alternative is optimized for a different question. The spreadsheet answers "who is on the list." The LMS answers "who attended." The HCM answers "what does HR think this person's skills are." Competency management software answers "who can do this work, at what level, and how do we know." The Evaluation Checklist Twelve items. A vendor should demonstrate each one live, on your data or a realistic sample, not on a slide. Define a competency with our own name, description, and a four- or five-level scale with behavioral anchors we write. Map that competency to a role with a required level, and show a person's gap against it. Record a supervised practical sign-off with a named qualifier and an attached checklist. Record a test result and a certification on the same competency without overwriting the sign-off. Attach an expiry to the certification and show where expiring items surface. Link an assessment to a specific procedure revision and show what happens when the revision changes. Generate the training matrix for a site live, filtered to one shift. Show the audit trail for one record: every change, who, when, prior value. Show a report an ISO or FDA auditor would accept without a spreadsheet export. Show how a manager without system training reads their team's status. Show the API or export path for the full competency record. Show the security posture: SSO, role-based access, data residency, and a current SOC 2 report. Any item the vendor defers to "the next release" or "a partner" is an item you will be doing by hand. The First Ninety Days Implementation fails on the framework, not on the software. Plan accordingly. Weeks one to four: define. Pick one operational area, one site, one shift if necessary. Define the competencies for the roles in that area with the people who do the work. Write the behavioral anchors for each level. Decide the assessment method and reassessment interval for each competency. This is the hard part and it cannot be skipped or outsourced entirely. Weeks five to eight: baseline. Load the framework. Record current competence for everyone in scope, using evidence where it exists and supervised assessment where it does not. Expect the baseline to reveal gaps nobody had written down. That is the system working. Weeks nine to twelve: operate. Run the training matrix in the daily stand-up. Close the first gaps. Reassess the first expiring items. Run a mock audit against the records. Then expand to the next area with the framework pattern already proven. Organizations that try to define every competency for every role before loading anything spend a year in workshops. Start narrow, prove the loop, widen. What It Costs to Get Wrong A mid-sized manufacturer passes its ISO 9001 surveillance audit for years on LMS completion records. A new auditor asks a different question: show me evidence that the operators who ran the critical fill line in the last quarter were competent against the current work instruction. The LMS shows completions from the original onboarding, three revisions ago. The supervisor knows who is competent and says so. The auditor writes a major nonconformity because knowing and proving are different things. The corrective action takes nine months. It involves rebuilding qualification records from memory and paper, reassessing eighty operators, and buying software under deadline pressure. The finding recurs at the next audit because the software chosen could not link a qualification to a procedure revision. None of this is exotic. It is the most common story in the category, and the cost is measured in months of management attention, not license fees. Where SkillsDB Fits SkillsDB is competency management software built for organizations that need to prove competence rather than record training: frameworks defined in the customer's own language, assessment with multiple methods and attached evidence, proficiency and currency tracking with expiry, native gap analysis, live training matrices, and a full audit trail, with SOC 2 Type II and enterprise access controls. It is the right choice for regulated and safety-critical operations from mid-market to enterprise. It is not the right choice for a team that only needs to track course attendance. Competence Is a Claim Every training matrix, every qualification card, every "yes, she's qualified" in a shift handover is a claim about what a person can do. Competency management software has one job: to make that claim provable, to the auditor, to the customer, and to the person who has to decide who runs the line tonight. Choose the tool that can answer "how do we know." Everything else is a records system. FAQ What is competency management software? Competency management software maintains a defensible record of who is competent to do what, at what proficiency level, based on which evidence, as of which date. It holds a competency framework, records assessments using multiple methods, tracks proficiency and expiry, computes gaps, generates a training matrix, and keeps an audit trail. It proves people can do the work, where a learning management system proves they attended training. What is the difference between a competency management system and an LMS? An LMS delivers and records training: courses assigned, completed, and scored. A competency management system records demonstrated competence: practical sign-offs, tests, observations, and certifications against a defined proficiency level, with expiry and an audit trail. Regulated organizations typically need both, with the LMS feeding evidence into the competency system. Does ISO 9001 require competency management software? No standard mandates a specific tool. ISO 9001 clause 7.2 requires organizations to determine necessary competence, ensure people are competent, and retain documented evidence. Software is not required, but spreadsheets and LMS completion records frequently fail to satisfy auditors on the "documented evidence of competence" point, which is why most organizations that receive a finding adopt dedicated software. Can we use a spreadsheet for competency management? For a single site with fewer than about fifty people and one dedicated owner, a well-structured spreadsheet can work. It breaks on audit trail, evidence attachment, expiry tracking, and continuity when the owner changes roles. Most organizations outgrow it the first time an auditor asks for the history of a single record. How long does it take to implement competency management software? A focused first phase covering one operational area typically takes about ninety days: four weeks to define the framework, four to baseline current competence, four to operate and prove the loop. Most of the effort is defining competencies and anchors with the people who do the work, not configuring software. Enterprise-wide rollouts are phased from that first proven area. What should competency management software cost? Pricing varies widely by vendor and by whether the product is a point solution, a suite module, or a purpose-built platform. Evaluate total cost including implementation time and internal effort to define the framework. A system that cannot survive an audit costs far more in corrective actions and management time than the difference between license tiers. --- ## Skills Intelligence Platforms: The Buyer's Landscape in 2026 URL: https://skillsdb.com/blog/skills-intelligence-platforms-buyers-landscape Five years ago "skills intelligence" was a phrase a handful of vendors used to describe themselves. Today it is a line item in the roadmap of every HCM suite, every learning platform, every talent marketplace, and a growing number of AI startups. Analyst firms now publish landscape reports on it. Boards ask about it. Procurement teams issue RFPs for it. Quick reference: Skills Intelligence Platform — the short version of this post, with the one table that matters. The result is a buying environment where six structurally different kinds of software answer the same search query, and the differences that matter most are the ones hardest to see in a demo. This post is the map. Not a ranking, and not a definition; what skills intelligence is has been covered. This is how the category breaks down, what every serious platform has to do, and the questions that separate the ones that produce data you can act on from the ones that produce a dashboard. What a Skills Intelligence Platform Actually Is A skills intelligence platform is a system of record for what people in an organization can do: it holds a skills library defined in the organization's own language, assesses individuals against those skills on a proficiency scale, calculates the gap between what roles require and what people have, and feeds that gap into planning decisions such as succession, internal mobility, workforce strategy, and learning. It is distinct from skills tracking, which records skills without measuring them; from a learning platform's skills tab, which infers skills from course completions; from an HCM skills module, which stores skills as a profile attribute alongside payroll data; and from a talent marketplace, which matches people to opportunities but rarely verifies the skills it matches on. The defining test is whether a leader can ask "who is currently qualified to do this, and how do we know" and get an answer the organization would stake a decision on. The Five Capabilities Every Platform Must Have Strip away the positioning and every credible skills intelligence platform is doing the same five things. If a product cannot do one of them natively, it is a component, not a platform. A skills library in your language. The taxonomy has to reflect how your organization actually describes work, mapped to your roles and your proficiency levels. Pre-built industry taxonomies demo beautifully and then sit unused, because no two organizations define "project leadership" the same way. The library is the foundation; if people do not recognize the skills in it, nothing built on top gets adopted. Assessment and proficiency. Skills have to be measured, not just listed, against a scale with defined levels. The platform should support several assessment methods on the same skill and keep them separate: a self-rating, a manager rating, and a certification are three different pieces of evidence. Gap analysis. Required level minus assessed level, at the person, team, role, and site level, computed inside the system. This is where a list of skills becomes intelligence. Planning. Succession, mobility, and workforce planning have to read directly from the gap data. If planning happens in a separate tool fed by an export, the intelligence is stale by the time it is used. Learning connection. Gaps should resolve into development actions, and completed development should flow back into a reassessment. A platform that ends at "here is your gap" has done half the job. The five are sequential. Each one depends on the quality of the one before it. Weak assessment produces meaningless gaps, and meaningless gaps produce planning nobody trusts. The Landscape by Category Six kinds of vendor now sell into this space. Each has a real strength and a real stopping point. Category What it does well Where it stops Enterprise AI talent platforms Broad talent intelligence across recruiting, mobility, and workforce planning; strong external labor-market data Skills are largely inferred from résumés and job history; verification of what employees can actually do is thin; built for very large enterprises and priced that way Talent marketplaces Matching people to internal gigs, projects, and roles; strong employee-facing experience Matching runs on self-declared or inferred skills; little assessment infrastructure; the marketplace is the product, the skills data is a means to it AI skills engines (inference-only) Fast bootstrapping of a skills inventory from existing data; taxonomy generation; labor-market benchmarking No assessment loop; the output is a well-designed estimate that never gets confirmed; weak on compliance evidence Skills assessment vendors Rigorous testing and question libraries; strong for hiring screens and technical certifications Built around the test event, not the ongoing record; limited gap analysis and planning; weak connection to development HCM suite skills modules Already in the building; skills as a profile attribute integrated with core HR data A field, not a system; generic taxonomy; assessment is shallow; gap analysis and planning are add-ons or absent; L&D rarely owns it Point solutions Focused, usable, fast to deploy; often excellent at a skills matrix or a training matrix Narrow; scale and enterprise requirements (SSO, audit trail, API, multi-language) arrive late or not at all Purpose-built skills intelligence platforms sit across these categories: they take the assessment rigor of the testing vendors, the planning scope of the enterprise platforms, and the usability of the point solutions, and put a verified skills record at the center. Fewer vendors occupy this space than the marketing suggests. The Inference Question The loudest debate in the category is whether skills should be inferred by AI or assessed by people. It is the wrong debate, because the answer is both, in order. Inference is the right way to start. Asking ten thousand employees to build their skills profiles from a blank page produces a slow, incomplete inventory. Inferring a first draft from job history, project records, and system activity produces a full inventory in weeks. Every serious platform should do this. Inference is the wrong way to finish. An inferred skill is a hypothesis. The engineer whose profile says "Kubernetes: advanced" because she was on a team that used it may or may not be able to run a production cluster. For a career suggestion, the hypothesis is fine. For staffing a critical project, planning succession for a key role, or proving competence to an auditor, it has to be verified by a human method: manager assessment, peer review, a test, or dated evidence. The question to ask a vendor is not "do you use AI" but "what happens to an inferred skill after you infer it." Platforms with an assessment loop can answer. Platforms without one change the subject to their algorithm. Ten Questions to Ask Any Vendor Can we define our own skills, proficiency levels, and behavioral anchors, or do we adopt yours? How many assessment methods can one skill carry at the same time, and are they stored separately? Can evidence, such as a certificate or a supervisor sign-off, attach to a specific assessment record with a date? Does every assessed skill carry a reassess-by date, and does the system surface what is expiring? Is gap analysis computed natively at the person, team, role, and site level, or does it require an export? Can a succession plan or a staffing decision read directly from current proficiency data? What happens to an inferred skill after inference? Show the verification path. Show the audit trail for a single skill record: every change, who made it, when, from what value. What is the API surface? Can we pull the full skills record into our own analytics? Which customers in a regulated industry have passed an audit using this data, and can we speak to one? A vendor who answers all ten with a demo rather than a slide is selling a platform. A vendor who answers three is selling a feature. Who Fits Which Category Very large enterprises with a mature HCM and a recruiting-heavy mandate often start with an enterprise AI talent platform, then discover the assessment gap when compliance or succession asks for proof. Budget for a verification layer. Organizations whose main goal is internal mobility and engagement get real value from a talent marketplace, provided they accept that the matching runs on unverified skills. Pair it with assessment for the roles where a mismatch is costly. Regulated and safety-critical operations , in manufacturing, aviation, energy, life sciences, and data centers, need the verified record first. Inference-only and marketplace products will not survive an audit. This is where purpose-built platforms and the better point solutions earn their place. Organizations already standardized on an HCM suite should ask hard questions of the built-in skills module before buying anything else, and then ask harder questions about whether L&D can actually operate it. Mid-market organizations without a dedicated HR technology team are best served by something usable in weeks, which usually means a point solution or a purpose-built platform with a fast implementation path, not an enterprise suite. Where SkillsDB Sits SkillsDB is a purpose-built skills intelligence platform, in the market since 2008, designed around a verified skills record: assessment with multiple methods and evidence, proficiency scales in the customer's own language, native gap analysis, and planning that reads from live data. It is strongest for mid-market to enterprise organizations that need skills data they can staff against and audit against, and it is not the right choice for a buyer whose primary need is external recruiting intelligence. The gap analysis capability is the center of the platform because the gap is the point. A category-by-category comparison is in the skills management software guide . The Category Is Converging. The Data Is Not. Every vendor in this landscape is moving toward the same five capabilities. In three years the feature checklists will look nearly identical. What will not converge is the quality of the underlying skills data, because that depends on decisions the software cannot make for you: how skills are defined, how they are assessed, how often, and by whom. The platforms worth buying are the ones that make those decisions visible and enforceable. The rest will produce beautiful dashboards of numbers nobody in the operation believes. FAQ What is a skills intelligence platform? A skills intelligence platform is a system of record for workforce skills that defines a skills library in the organization's own language, assesses people against a proficiency scale, calculates gaps between role requirements and actual proficiency, and feeds those gaps into succession, mobility, workforce planning, and learning. It differs from skills tracking, learning platforms, and HCM skills fields by measuring skills rather than just recording them. Is a skills intelligence platform the same as a skills taxonomy? No. A taxonomy is the structured list of skills and how they relate. It is one component of a platform. A platform adds assessment, proficiency levels, gap analysis, planning, and learning connection on top of the taxonomy. Many vendors sell taxonomies as if they were platforms. Do we need a skills intelligence platform if we already have an HCM suite? It depends on what you need the skills data to do. HCM skills modules store skills as profile attributes and are adequate for basic reporting. If you need verified proficiency, evidence for audits, native gap analysis, or planning that L&D can operate without IT, most organizations find the module insufficient and add a dedicated platform integrated with the HCM. Should skills be inferred by AI or assessed by people? Both, in sequence. Inference is the fastest way to build an initial inventory from existing data. Assessment by managers, peers, tests, or evidence is how those inferred skills get verified before a real decision depends on them. Ask any vendor what happens to an inferred skill after it is inferred. How long does it take to implement a skills intelligence platform? A focused implementation covering one function or business unit typically runs eight to sixteen weeks, most of it spent defining the skills library and proficiency scales rather than configuring software. Enterprise-wide rollouts run longer and are usually phased. Vendors quoting a few days are describing the technical setup, not the program. What should a skills intelligence platform cost? Pricing models vary from per-employee subscriptions to platform fees, and the range across categories is wide. The more useful question is total cost including implementation and the internal time to define skills and run assessments. A cheaper tool that nobody trusts costs more than an expensive one the operation runs on. --- ## Skills Assessment: Methods, Tools, and How to Choose URL: https://skillsdb.com/blog/skills-assessment-methods-and-tools Every organization already assesses skills. The manager who decides who gets the hard project is assessing. The team lead who signs off a new hire on the line is assessing. The partner who staffs a client engagement from memory is assessing. The problem is that none of it is written down in a form anyone else can use, compare, or defend six months later. Quick reference: Skills Assessment — the short version of this post, with the one table that matters. That informal layer works until it has to scale. Three people on a team, fine. Three hundred across four sites, and the questions start arriving: who is actually qualified on this procedure, how do we know, and when did we last check. The answer to all three is a skills assessment that follows a method, lands in a record, and gets repeated. This post is about the choosing part. Which method fits which skill, where the line sits between assessing employees and screening candidates, and what to demand from any tool that claims to do it. If you want the argument for why assessment data has to be trustworthy before you build anything on it, that is a separate post . This one is the practical menu. What a Skills Assessment Is A skills assessment is a structured judgment of how well a specific person can perform a specific skill, recorded against a defined proficiency scale at a known point in time. Four elements make it an assessment rather than an opinion. The skill is named precisely, not "communication" but "runs a customer escalation call to resolution." The scale is defined in advance with observable behaviors at each level. The assessor and method are recorded, so a self-rating and a manager rating are never confused. And the date is captured, because a skill assessed three years ago tells you something different from one assessed last quarter. Together those four elements turn a scattered set of impressions into a comparable data point, which is what allows an organization to see gaps across a team, plan succession, or prove competence to an auditor. Without them, you have a survey. The Six Assessment Methods There are six ways to assess a skill in a workforce setting. Most organizations should use three or four of them, matched to the skill, not one method applied to everything. Method How it works Validity Cost to run Use it when Self-assessment Employee rates their own proficiency against the scale Low alone; useful as a starting point and for engagement Very low Building an initial inventory; low-risk skills; paired with another method Manager assessment Direct manager rates proficiency based on observed work Moderate; depends on manager exposure and calibration Low Skills the manager sees weekly; performance-linked skills Peer or 360 Colleagues and internal customers rate observed behavior Moderate to high for behavioral and collaborative skills Moderate Leadership, communication, cross-team skills the manager cannot observe Test-based Knowledge or practical test with scored outcome High for knowledge; moderate for applied skill Moderate to high Regulated knowledge, technical certifications, tool proficiency Evidence-based Proficiency confirmed by artifacts: certifications, completed work, supervised sign-off High when evidence is specific and dated Moderate Safety-critical procedures, licensed roles, compliance Inferred Proficiency estimated from work signals: systems used, projects completed, job history Low to moderate; a hypothesis, not a verdict Low once set up Bootstrapping a skills inventory at scale before human verification The table hides the most important point, so here it is directly. No single method is right for every skill. A forklift certification should be evidence-based. A senior engineer's system design ability should be assessed by peers who have reviewed their designs. A new analyst's spreadsheet proficiency can start as a self-rating and be validated by a test. The method is a property of the skill, decided when the skill is defined. On inference specifically Inferring skills from résumés, project history, and system activity has become common, and it is genuinely useful for one thing: getting a first draft of the inventory without asking 5,000 people to fill out forms. Treat that draft as a set of hypotheses. Then verify the ones that matter with a human method. Organizations that stop at the inferred layer end up with an impressive-looking skills map that nobody trusts when a real decision depends on it. Bootstrap with inference, verify with assessment. Skills Assessment vs. Pre-Employment Testing Two things share the phrase "skills assessment" and they are not the same product. Pre-employment testing screens candidates. Its job is to rank strangers on a narrow set of skills in a single sitting, with the emphasis on cheat-resistance and speed. The output is a hiring decision. Once the candidate is hired, the test result is rarely looked at again. Workforce skills assessment measures people you already employ, repeatedly, against the full set of skills their role requires. Its job is to produce a living record that feeds gap analysis, development plans, staffing, and compliance. The output is a data layer the organization runs on. The confusion matters because the tools built for the first job are poor at the second. A screening platform optimizes for proctoring and question banks. A workforce assessment system optimizes for scales, multi-rater input, evidence, currency, and what happens after the score is recorded. If a vendor demo spends most of its time on question libraries, you are looking at a screening tool. Designing an Assessment That Produces Comparable Data The value of an assessment is that it can be compared: this person to that person, this quarter to last quarter, this site to that site. Four design decisions determine whether comparison is possible. Pick one scale and define every level A 0 to 4 or 1 to 5 scale is standard. What makes it work is the behavioral anchor at each level. "Level 3: performs the task independently under normal conditions; escalates exceptions" is comparable across assessors. "Level 3: proficient" is not. Anchors should describe what you would see the person do, not how good they are. The full treatment of proficiency scales is in the proficiency levels post . Calibrate the assessors Two managers using the same anchors will still drift. A short calibration exercise, where five managers independently rate the same three anonymized cases and then discuss the differences, closes most of the gap. Repeat it annually and whenever a new manager starts assessing. This is the step most programs skip, and it is why their data varies more by assessor than by employee. Set the cadence per skill Compliance and safety skills need reassessment on a fixed schedule, often annually, sometimes quarterly. Fast-moving technical skills need reassessment when the underlying tool changes. Stable behavioral skills can go longer. Skills decay at different rates, so a single organization-wide cadence is either too frequent for some skills or dangerously infrequent for others. Set the interval when you define the skill. Record the method with the score A record that says "Level 3" is incomplete. A record that says "Level 3, manager-assessed by J. Ortiz on 2026-08-14, evidence attached" is usable. When the method travels with the score, you can weight self-ratings differently from evidence-backed ratings in every downstream report. The Assessment Record: A Template Whatever tool you use, every assessment should capture the same fields. If you are starting in a spreadsheet, these are your columns. Field Why it matters Person The individual assessed Skill The precise skill, from the shared library, not free text Required level for role So the gap is visible in the same row Assessed level The score on the defined scale Method Self, manager, peer, test, evidence, inferred Assessor Who made the judgment Date assessed Drives currency and reassessment Reassess by Calculated from the skill's decay interval Evidence Link or attachment: certificate, test result, sign-off, work sample Notes Context an auditor or the next manager would need A spreadsheet with these ten columns is a legitimate skills assessment system for a team of twenty. It stops being one somewhere around a hundred people, or the first time an auditor asks to see the history of a single row. What to Look for in Skills Assessment Software The category is crowded. Point solutions do one method well. Learning platforms bolt on a self-rating. HCM suites add a skills field. The test below separates tools that assess from tools that collect ratings. Scale flexibility You should be able to define your own levels and anchors per skill family. A tool that ships one fixed five-point scale for every skill in the organization will be wrong for most of them. Multiple assessment methods on the same skill A single skill should be able to carry a self-rating, a manager rating, and an evidence record at once, each stored separately. Tools that overwrite one with another destroy the comparison you need. Evidence attachments Certificates, test results, supervisor sign-offs, and work samples should attach to the specific assessment record, not to the person's profile in general. This is what makes a record defensible. Currency and expiry Every assessment should carry a reassess-by date driven by the skill's own interval. The system should surface what is expiring, not wait for someone to remember. Trained and current are different states, and the software should know the difference. Gap output The point of assessing is the gap. The tool should compute required minus assessed at the person, team, role, and site level without an export to a spreadsheet. If gap analysis is a separate module or a separate product, the assessment data is stranded. Audit trail Who changed what, when, and from what value. Regulated organizations need this to pass audits. Everyone else needs it the first time a promotion decision is challenged. SkillsDB was built around these six because they are what assessment data has to have before anything else, staffing, succession, learning plans, can rely on it. The proficiency assessment and surveys capabilities are two ways in; the shared record underneath is the same. Three Industries, Three Method Mixes Manufacturing line qualification. A packaging line has forty operators and twelve stations. Each station has three or four skills with a required level. The method mix is evidence-based for the initial qualification (supervised sign-off, documented), manager-assessed at ninety days, and test-based on a fixed annual cycle for the safety-critical steps. The output is a matrix the shift supervisor can read at 6 a.m. to see who can cover station seven. Data center operations. Technicians work across sites on procedures where a mistake takes down a customer. Critical procedures are evidence-based with a named qualifying engineer and a twelve-month currency window. Certifications from vendors are evidence records with expiry dates pulled from the certificate. Self-assessment is used only for the initial inventory of adjacent skills, and every self-rated critical skill is flagged until verified. Professional services bench. A consultancy staffing client work needs a defensible view of who can lead a workstream. Peer assessment from prior project leads carries the most weight. Manager assessment covers delivery behaviors. Inferred skills from project history seed the inventory for new joiners and are verified after their first engagement. The resource manager staffs from verified levels, not from the résumé. The Mistakes That Ruin Assessment Programs Assessing everything at once. A full-workforce assessment of every skill produces a mountain of self-ratings nobody validates. Start with the skills tied to a decision you have to make this quarter. Using one method because it is easy. Self-assessment for everything produces data that is systematically optimistic and unusable for compliance. Skipping calibration. The data ends up describing the assessors more than the employees. No reassessment cadence. The inventory is accurate on the day it is built and decays from there. Storing scores without methods or evidence. Every downstream report has to treat a guess and a certificate as equal. Treating the tool as the program. Software stores and computes. The method choices, anchors, and calibration are decisions people make, and they have to be made before the first assessment is entered. Assessment Is How an Inventory Earns Trust A skills inventory is a list of claims. Every row says this person can do this thing at this level. Assessment is the process that turns a claim into something a manager will staff against, an auditor will accept, and a leadership team will plan around. The method has to fit the skill, the scale has to be anchored, the assessors have to be calibrated, and the record has to carry its own provenance. Get those four right and the tool question mostly answers itself. Get them wrong and no tool will save the data. FAQ What is the most accurate skills assessment method? Evidence-based assessment, where proficiency is confirmed by a dated artifact such as a certification, test result, or supervised sign-off, is the most defensible for individual skills. For behavioral and collaborative skills, structured peer or 360 assessment is usually more accurate than manager assessment alone. Most organizations should combine two methods on any skill that drives a real decision. How often should skills be reassessed? It depends on the skill's decay rate, not on a company-wide calendar. Safety-critical and compliance skills typically need annual or more frequent reassessment. Technical skills should be reassessed when the underlying tool or procedure changes. Stable behavioral skills can go eighteen to twenty-four months. Set the interval when you define the skill. Is a skills assessment the same as a competency assessment? They overlap heavily and many organizations use the terms interchangeably. A skill is a discrete ability; a competency usually bundles skills, knowledge, and behaviors into a broader capability tied to a role. The assessment methods are the same. The difference is the granularity of what is being measured. Can we run skills assessments in a spreadsheet? Yes, for a small team and a limited set of skills. A spreadsheet with the ten fields in the template above is a legitimate starting point. It breaks down when you need multiple assessment methods on one skill, evidence attachments, expiry tracking, or an audit trail, which usually happens somewhere between fifty and a hundred people. What is the difference between skills assessment software and pre-employment testing software? Pre-employment testing screens candidates in a single sitting and optimizes for proctoring and question banks. Skills assessment software measures existing employees repeatedly against their role requirements and optimizes for scales, multi-rater input, evidence, currency, and gap analysis. They solve different problems and are rarely good at each other's job. Should employees see their own assessment results? Yes. Transparency improves the quality of self-assessments over time, makes development conversations concrete, and is expected by most workforces. The exception is where a specific regulatory or legal process requires restricted access, which should be defined per skill rather than applied to the whole system. --- ## Job Roles and Job Architecture in a Skills-Based Organization URL: https://skillsdb.com/blog/job-roles-and-job-architecture Ask a company how many job titles it has and the answer is usually a number that embarrasses someone. In 18 years of implementations we have routinely seen a title count that is a third of the headcount, sometimes higher. Titles multiply because they are cheap to create and expensive to reconcile, and because for years they were the only vocabulary HR had for describing work. Quick reference: Job Roles and Job Architecture — the short version of this post, with the one table that matters. Titles are not the problem. The problem is that titles were asked to carry weight they were never designed for: to describe what a person does, to define what they are paid, to signal where they can go next, and to tell a workforce planner what capability the organization has. A title does none of those things reliably. A role, properly defined, does all four. Job architecture is the discipline of building that vocabulary deliberately. It has been an HR specialty for decades, mostly in the service of compensation. What has changed is that skills data now exists at a level of detail that lets architecture describe the work itself rather than the box on the chart. That shift is why the term is suddenly showing up in consulting offers and vendor roadmaps, and why it is worth understanding before someone sells you a redesign. What Is a Job Role? A job role is a defined bundle of responsibilities and the skills, at specified proficiency levels, required to carry them out. It is independent of the person who holds it and of the title on their business card. A role describes work: what outcomes it owns, what decisions it makes, and what someone must be able to do to perform it well. Where a title is a label and a position is a funded seat, a role is the unit that connects people to capability. Two people with different titles can hold the same role. One title can span three genuinely different roles. In a skills-based organization, the role is where required skills are declared, where employees are assessed against them, and where gaps become visible. That makes it the anchor for development plans, internal mobility, succession slates, and workforce planning. Get roles right and the rest of the talent system has something solid to stand on. Role, Title, Position, Family Four terms that get used as synonyms and mean different things. Most job architecture failures trace back to conflating two of them. Term What it is Who owns it Example Job title A label used for identification and, often, status Manager, sometimes the employee "Senior Facilities Engineer II" Position A funded seat in the org chart with a reporting line Finance and HR Position 4471, reports to the Site Operations Manager Job role A defined set of responsibilities and required skills at set proficiency levels HR and the function leader "Critical Facilities Technician, Level 2" Job family A grouping of roles that share a body of knowledge and a progression HR "Facilities Operations" The useful mental model: families contain roles, roles are filled by positions, positions are held by people who have titles. A person's title might be historical, negotiated, or aspirational. Their role is a statement of what the organization needs them to be able to do. What Job Architecture Is Job architecture is the structured framework that organizes every role in the company into families and levels, defines what each role requires, and describes how roles relate to one another. It is the map of the work. A complete architecture has four components. Job families. The major bodies of work: engineering, operations, sales, finance, clinical, and so on. Typically eight to twenty for a mid-sized organization. Families are stable; they change when the business changes, not when the org chart does. Levels. The rungs within a family, from entry to principal or executive. Levels are defined by scope, autonomy, and impact, and each level has anchors that describe what changes as you move up. A five- to seven-level ladder covers most families. Role profiles. The intersection of a family and a level, plus the specific responsibilities and required skills. "Software Engineer, Level 3" is a role profile. So is "Quality Inspector, Level 1." The profile declares which skills are required and at what proficiency. Required skills and proficiency levels. The part that makes the architecture usable for anything beyond pay. Each role profile lists the skills it depends on, drawn from a shared skills library, and the proficiency level required for each. Level 2 might require competence in a procedure; Level 4 might require the ability to train others on it and revise it. The first three components describe structure. The fourth connects structure to capability, and it is the component most architectures are missing. Why It Matters in a Skills-Based Organization An architecture built for compensation alone answers one question: what should this seat be paid? An architecture built on skills answers several more, and they are the questions leadership is actually asking. Internal mobility. When roles declare required skills, an employee can see exactly what separates them from a role two families over. A recruiter can search for internal candidates who already hold 70% of the required skills instead of posting externally. Mobility stops being a matter of who knows whom. Succession. A succession slate built from titles is a list of names. One built from role profiles is a list of names with the specific gaps each candidate needs to close, and the development plan to close them. The conversation moves from "who is ready" to "what would it take for these three people to be ready." Pay equity. Consistent role definitions across families are the foundation of any defensible pay structure. Two people doing the same work under different titles is the pattern that shows up in equity audits, and architecture is how you find it before the audit does. AI-driven task change. Roles are being reshaped task by task as automation absorbs parts of the work. An architecture that describes roles as skill bundles can be updated skill by skill. One that describes roles as titles has to be torn up and redrawn. Workforce planning. Headcount planning tells you how many seats you will have. Skills-based architecture tells you what those seats need to be able to do, which is the number planners have been guessing at for years. We wrote about that gap in workforce strategy is capability planning . How to Build a Job Architecture From Skills Data Most architecture projects start from the org chart and work down to skills. Start from the work and build up. Step 1: Inventory the work, not the titles Collect what people actually do: responsibilities from current job descriptions, procedures they execute, decisions they own, tools they use. Interview managers about what their best performer does that others do not. The output is a messy list of responsibilities and skills, and that is fine. Cleaning it is the next step. Step 2: Consolidate into a skills library Merge duplicates and normalize language so that every skill has one name and one definition across the company. This library is the shared vocabulary the entire architecture depends on. A skills library built in the organization's own terms gets adopted; one imported from an industry taxonomy gets ignored. Step 3: Define families and levels Group the work into families by shared body of knowledge and career progression. Then define levels within each family with behavioral anchors: what scope, autonomy, and impact look like at each rung. Keep the number of levels honest. Seven levels with clear anchors beats twelve levels that exist to justify legacy titles. Step 4: Write role profiles with required proficiency For each family-and-level intersection that exists in the organization, write the role profile: responsibilities, decision rights, and the eight to fifteen skills that matter most, each with a required proficiency level. This is where the architecture becomes something an employee can be assessed against. Step 5: Map people to roles and assess Place every employee in a role. Then assess them against the role's required skills. The result is, for the first time, a company-wide view of who meets their role requirements, who exceeds them, and where the gaps concentrate. Expect surprises. Titles have been hiding both under-qualified incumbents and over-qualified people who should have been promoted a year ago. Step 6: Connect the architecture to decisions Wire the role profiles into development planning, internal job posting, succession, and workforce planning. An architecture that lives in a compensation spreadsheet is a compliance artifact. One that drives the internal mobility search and the succession slate is a management system. A Worked Role Profile Consider "Critical Facilities Technician, Level 2" in the Facilities Operations family at a data center operator. Scope. Operates and maintains electrical and mechanical infrastructure on an assigned shift. Executes standard procedures unsupervised. Escalates non-standard conditions to Level 3 or the shift lead. Required skills and proficiency (five-level scale: 1 awareness, 2 developing, 3 competent, 4 advanced, 5 expert): Skill Required level Evidence type Electrical distribution operations 3 Assessed Generator load transfer procedure 3 Assessed, current within 12 months Chiller plant operations 3 Assessed Building management system monitoring 3 Manager-validated Fire and life safety systems 2 Certification Work order and CMMS documentation 3 Manager-validated Lockout-tagout 3 Certification, current Vendor escalation and incident communication 2 Manager-validated Level 3 in the same family raises generator load transfer and chiller operations to level 4 (executes alone, trains others), adds "procedure revision and review" at level 3, and requires incident command at level 3. Level 1 drops most skills to level 2 and adds a supervision requirement. Now the profile does real work. A Level 1 technician can see the exact three skills that stand between them and Level 2. A shift lead can see that the site has five people who hold Level 2 titles but only three who meet the Level 2 profile on generator load transfer currency. A succession conversation about the Level 3 opening starts with a list of who is one skill away. The same structure applies anywhere. A "Senior Consultant" profile at a services firm lists client discovery, proposal writing, workstream leadership, and two or three domain skills, each with a required level. A "Charge Nurse" profile lists clinical skills, delegation, and unit coordination. The vocabulary changes; the shape does not. Where Job Architectures Fail Three failure modes account for most of the architectures that get built and then quietly abandoned. Built from titles instead of work. The project starts by mapping existing titles into a grid, which preserves every historical inconsistency the architecture was supposed to fix. If the starting material is the org chart, the output is the org chart with pay bands attached. Levels without anchors. "Level 4" is defined as "more than Level 3." Without behavioral descriptions of what changes at each level, managers level people by tenure and negotiation, and the architecture reproduces the problem it replaced. Frameworks that never connect to assessment. The architecture declares required skills but nobody is ever assessed against them. The profiles become aspirational documents in a shared drive. The signal that this has happened: a year after launch, no development plan references a role profile and no internal move was informed by one. The common thread is that the architecture was treated as a document to be completed rather than a system to be run. Architecture that is not connected to a career framework employees can see, and to assessment data that updates, decays as fast as the titles it replaced. What Changes When Roles Are Built on Skills The organization gets a shared vocabulary for work that survives reorganizations. Employees get a visible path: this is my role, this is the next one, these are the specific skills between them. Managers get a succession conversation grounded in evidence. Planners get a capability view instead of a headcount view. And when a task inside a role gets automated, the architecture absorbs the change skill by skill instead of requiring a redesign. A job architecture built this way is not a compensation exercise with talent benefits. It is the structure that succession planning and career pathways both depend on, and the reason they so often fail is that the structure underneath them was never built. People do not quit companies. They quit careers they cannot see. Job architecture, done from the work up, is how you make the career visible. FAQ What is a job role? A job role is a defined set of responsibilities together with the skills, at specified proficiency levels, required to perform them. It is independent of the person holding it and of their job title. In a skills-based organization the role is the unit that connects people to capability, and the thing employees are assessed and developed against. What is the difference between a job role and a job title? A job title is a label used for identification and status, and it often reflects history or negotiation rather than the work. A job role describes the actual responsibilities and required skills. Two people with different titles can hold the same role, and a single title can cover several distinct roles. What is job architecture? Job architecture is the framework that organizes all roles in an organization into job families and levels, defines each role's responsibilities and required skills, and describes how roles relate to one another. Its four components are families, levels with behavioral anchors, role profiles, and the required skills and proficiency levels attached to each profile. Why does job architecture matter for skills-based organizations? Because roles built on skills can be assessed, compared, and updated. That makes internal mobility searchable, succession planning evidence-based, pay equity defensible, and workforce planning about capability rather than headcount. Architectures built from titles alone cannot support any of those uses. How many levels should a job architecture have? Most organizations land between five and seven levels per job family. The number matters less than the anchors: each level needs an observable description of the scope, autonomy, and impact that distinguish it from the level below. Adding levels to accommodate legacy titles is the most common way architectures lose credibility. How do you keep a job architecture current? Treat it as a system rather than a document. Assess employees against role profiles on a regular cadence, update required skills when the work changes, and connect the profiles to development planning, internal postings, and succession reviews. An architecture that drives real decisions gets maintained; one that sits in a compensation file decays within a year. --- ## Skills Inventory: What It Is and How to Build One That Stays Current URL: https://skillsdb.com/blog/skills-inventory-how-to-build Every organization has a skills inventory. Most of them just don't know where it is. Quick reference: Skills Inventory — the short version of this post, with the one table that matters. It lives in the heads of a few senior managers who know that Priya is the only person who can run the chiller failover procedure, that two of the four welders certified on stainless left last spring, and that the analyst everyone routes Tableau questions to is on parental leave until November. When one of those managers leaves, the inventory leaves with them. When an auditor asks who is qualified to do what, someone spends a week rebuilding it from training records and memory. The formal version of that knowledge, written down, structured, and kept current, is what a skills inventory is supposed to be. Very few organizations have one that anyone trusts. This is how to build one that earns trust and keeps it. What Is a Skills Inventory? A skills inventory is a structured record of the skills each person in an organization holds, the proficiency level they hold each skill at, and the evidence behind that rating. It is organized by person, not by job or by course. Each row answers a simple question: what can this individual actually do today, and how do we know? A complete inventory covers technical and behavioral skills, certifications with their expiry dates, and the recency of each rating, so it can distinguish someone who performed a skill last month from someone trained on it six years ago. Its purpose is operational. Resource planners use it to staff work, L&D uses it to target development, leadership uses it to see capability and gaps across teams and sites. When the inventory is current and verified, it becomes the source of truth every other workforce decision draws on. When it isn't, it is a spreadsheet people stop opening. Inventory, Matrix, Database: Three Different Things The terms get used interchangeably, and the confusion costs teams real time. They describe three different views of the same underlying data. Term Organized by Answers Typical form Skills inventory Person What can each individual do, at what level, with what evidence? One record per employee Skills matrix Team or role Who on this team covers which required skills, and where are the gaps? Grid of people against skills Skills database Organization Where does every skill exist across the company, and how has it changed over time? Queryable system of record The inventory is the raw material. A skills matrix is a view on top of it, filtered to one team and one set of required skills. A skills database is what you get when the inventory is stored somewhere it can be searched, versioned, and connected to roles, learning, and hiring. You cannot build a good matrix without a good inventory underneath it. Teams that start with the matrix, drawing a grid and asking managers to fill in checkmarks, end up with a picture of opinions rather than a record of capability. What to Capture for Each Person An inventory that only lists skill names is a résumé. The fields that make it useful are the ones that describe how well, how recently, and how verified. The skill itself. Drawn from a shared skills library so that "SQL" means the same thing in Finance as it does in Engineering. Free-text skill entry is the fastest way to end up with fourteen spellings of the same competency. Proficiency level. A rating on a defined scale, typically four or five levels with behavioral anchors. "Advanced" means nothing until the organization has written down what an advanced practitioner can do that a competent one cannot. Evidence. How the rating was established. Self-reported, manager-validated, assessed against a rubric, demonstrated on the job, or inferred from a certification. The evidence type is what separates a rating you can act on from one you cannot. Certifications and their expiry dates. Forklift, first aid, AWS Solutions Architect, welding procedure qualifications, board certifications. Each has a date it stops being valid, and the inventory should know that date before the auditor does. Recency. When the skill was last assessed, performed, or refreshed. A skill assessed at level 4 three years ago is not the same as one assessed at level 4 last quarter. The difference between trained and current is the difference between a record and a capability; we wrote about that distinction in skills currency vs. skills completion . Decay profile. Some skills hold for a career. Others fade within months without practice. Knowing which is which, the durable versus perishable split, tells you how often each entry needs to be revisited. How to Build a Skills Inventory in Five Steps Step 1: Define the skills library Start with the work, not with a taxonomy. Pull the skills that actually appear in role descriptions, standard operating procedures, project staffing requests, and audit requirements. For a 200-person organization this usually lands between 150 and 400 skills once duplicates are merged. Resist the urge to import a pre-built industry taxonomy of several thousand items. They look complete in a demo and collapse in practice, because nobody in the organization recognizes the language. A library written in the company's own terms, mapped to its own roles, gets used. A borrowed one becomes shelfware. Step 2: Choose the proficiency scale Pick one scale and use it everywhere. A five-level scale (awareness, developing, competent, advanced, expert) works for most organizations. What matters more than the number of levels is that each level has an observable anchor: what someone at that level can do, unassisted, in real conditions. Write the anchors for a handful of high-stakes skills first. A data center operator at level 3 on "generator load transfer" can execute the procedure under supervision. Level 4 executes it alone and trains others. Level 5 writes and revises the procedure. Once managers see anchors like these, rating stops being a guess. Step 3: Collect ratings from three angles Self-assessment is fast and gets coverage. It is also systematically wrong in predictable ways: junior people overrate, senior people underrate, and everyone rates against a different mental scale. Use it as the first pass, not the final answer. Manager validation is the second pass. The manager confirms, adjusts, or flags each self-rating. Disagreements are useful data; a gap of two levels between self and manager is a conversation worth having. Structured assessment is the third angle, reserved for skills where the cost of being wrong is high. Safety-critical procedures, customer-facing technical work, anything an auditor will ask about. Assessment against a rubric produces the ratings you can defend. Step 4: Verify and attach evidence Every rating carries its evidence type. Self-reported ratings are visibly marked as such. Certifications link to the document and the expiry date. Assessed ratings link to the assessment record. This is the step most inventories skip, and it is the reason most inventories die. A rating with no provenance cannot be trusted, and an inventory nobody trusts is not consulted, and an inventory nobody consults is not maintained. Step 5: Publish it and connect it to decisions An inventory that only L&D can see is an L&D project. Publish the relevant views to the people who make decisions with them: resource managers staffing projects, plant managers covering shifts, HR business partners building succession slates. Then wire it into the decisions themselves. When a project request comes in, the staffing shortlist is pulled from the inventory. When a certification is 60 days from expiry, the renewal is triggered from the inventory. When a role opens, the internal candidate search runs against the inventory. The moment the inventory drives a decision someone cares about, it starts getting maintained. A Worked Example: A 40-Person Data Center Operations Team Consider a critical facilities team across two sites: 40 technicians, four shift leads, one operations manager. The skills library lands at 62 skills after consolidation: electrical distribution, mechanical cooling, controls and BMS, fire and life safety, vendor-specific UPS platforms, and a set of procedures unique to each site. Fourteen of the 62 are tied to certifications with expiry dates. Nine are designated safety-critical and require assessed ratings rather than self-reported ones. The first pass takes three weeks. Self-assessment goes out on a Monday. Shift leads validate over the following two weeks during regular one-on-ones. The nine safety-critical skills are assessed by the operations manager using the site's existing qualification checklists, which turn out to be perfectly usable rubrics once someone attaches a proficiency level to each line. What the inventory reveals in week four: 31 of 40 technicians are rated competent or above on generator load transfer, but only six are current, meaning they have performed or been assessed on it in the last twelve months. Three of those six are on the same shift. Site B has one person, not the assumed three, who can execute the chiller failover unsupervised. Two forklift certifications expired in the spring and nobody noticed. None of that was visible in the training records. All of it was known, in fragments, by individual shift leads. The inventory did not create the knowledge. It made it shared, dated, and actionable. Keeping It Current The failure mode of every skills inventory is the same: it is accurate on launch day and decays from there. Three practices prevent it. Re-assessment cadence tied to decay. Durable skills get revisited annually. Perishable, procedural, or safety-critical skills get a shorter cycle, quarterly or tied to the frequency the work actually happens. A skill that has not been performed in its window drops from "current" to "lapsed" automatically, without waiting for someone to remember. Events that update the record. Completed training, a passed assessment, a renewed certification, a project role held for six months. Each is a signal that should change a rating or a recency date. Inventories maintained only by annual review are always eleven months stale. A named owner per skill group. Not the L&D team in aggregate. The controls lead owns the controls skills. The quality manager owns the compliance skills. Ownership is what turns "someone should update this" into a thing that happens. The Spreadsheet Version, and When It Breaks A skills inventory can start life in a spreadsheet, and for a single team under 50 people it should. The columns you need: Employee, role, site or team Skill (from the library, not free text) Proficiency level (on the shared scale) Evidence type (self, manager, assessed, certification) Date last assessed or performed Certification expiry date, where relevant Decay class (durable or perishable) and next review date That is a serviceable inventory. It breaks in three predictable ways. It breaks at scale. Above 50 people the sheet stops fitting on a screen, and above two teams nobody agrees on which copy is the real one. It breaks across sites. Two plants running two spreadsheets is not an organizational inventory; it is two local ones that cannot be compared. And it breaks under audit. The moment an ISO or FDA auditor asks for the history of a rating, who changed it, when, and based on what, the spreadsheet has no answer. What to Look For in Skills Inventory Software When the spreadsheet breaks, the question becomes what to replace it with. The distinguishing features are not the ones on the pricing page. A shared, governed skills library that the whole organization draws from, with an owner for each skill and a change history. Proficiency scales with anchors built in, not a one-to-five dropdown. Evidence attached to every rating. Certification expiry tracking that triggers renewal before the lapse. Recency and decay handled as properties of the skill, not as a manual field someone updates. And search that works the way a resource planner actually thinks: everyone at level 4 or above on this skill, current within twelve months, at this site, available next month. That is what turns an inventory into a searchable capability record rather than a document. The best test is simple. Ask a shift lead or a resource manager to find the right person for a real, specific need using only the system. If they reach for their phone to call someone who "would know," the inventory is not doing its job yet. Infrastructure, Not a Document A skills inventory nobody trusts is a spreadsheet, and it will be abandoned within a year regardless of how carefully it was built. A skills inventory everybody trusts is infrastructure. Staffing runs on it. Compliance runs on it. Development plans start from it. Succession conversations reference it. The difference between the two is not the tool or the template. It is whether every rating carries evidence, whether recency is tracked instead of assumed, and whether the inventory is connected to a decision someone makes every week. Build for those three things and the inventory maintains itself, because the people who depend on it will not let it go stale. FAQ What is a skills inventory? A skills inventory is a structured record of the skills each employee holds, the proficiency level of each skill, and the evidence behind that rating. It is organized by person and typically includes certifications, expiry dates, and how recently each skill was assessed or used. Its purpose is to make workforce capability visible so it can be used for staffing, development, and compliance decisions. What is the difference between a skills inventory and a skills matrix? A skills inventory is organized by person and records everything each individual can do. A skills matrix is organized by team or role and shows which people cover which required skills, usually as a grid. The matrix is a view built on top of the inventory; you need the inventory data first to produce a reliable matrix. How do you conduct a skills inventory? Define a shared skills library drawn from real work, choose one proficiency scale with observable anchors, then collect ratings through self-assessment, manager validation, and structured assessment for high-stakes skills. Attach evidence and dates to every rating, publish the results to the people who make staffing and development decisions, and set a re-assessment cadence based on how quickly each skill decays. What should a skills inventory template include? At minimum: employee, role, team or site, skill name from a shared library, proficiency level on a common scale, evidence type, date last assessed or performed, certification expiry date where relevant, and a next review date. Free-text skill names and unanchored ratings are the two most common template mistakes. How often should a skills inventory be updated? Continuously, in response to events such as completed training, passed assessments, renewed certifications, and time spent in a role. On top of that, set a review cadence by skill type: annually for durable skills, quarterly or per-use for perishable and safety-critical skills. An inventory refreshed only by annual review is stale most of the year. When should you move a skills inventory from a spreadsheet to software? When it covers more than about 50 people, spans more than one team or site, or needs to survive an audit. At that point a spreadsheet loses a single source of truth, cannot be compared across locations, and has no history of who changed a rating and why. Skills inventory software adds a governed skills library, evidence tracking, expiry alerts, and search. --- ## Proficiency Levels: Scales, Examples, and How to Define Them URL: https://skillsdb.com/blog/proficiency-levels-scales-examples Two maintenance technicians both have "hydraulic systems" on their skills record. One can swap a failed pump from a work order. The other can diagnose an intermittent pressure drop across a 40-valve manifold that has stumped the shift for a week. The record says the same thing about both of them. The scheduler, the training manager, and the succession plan all treat them as interchangeable, and every one of those decisions is wrong. Quick reference: Proficiency Levels — the short version of this post, with the one table that matters. This is the problem proficiency levels exist to solve. A skill without a level is a label. A skill with a level is a measurement. The difference determines whether your skills data can carry any weight at all. What Are Proficiency Levels? Proficiency levels are the defined stages of capability on a single skill, arranged on a scale from no ability to full mastery, with each stage described by observable behavior. A typical scale runs from 0 to 5 or from novice to expert. What makes a level meaningful is not the number but the anchor attached to it: a plain description of what a person at that level can do, under what conditions, and with how much support. Level 2 in root-cause analysis might mean "identifies probable causes for routine failures with guidance from a senior." Level 4 might mean "leads structured analysis on unfamiliar failures and validates the corrective action." Because the anchors are behavioral, two assessors looking at the same person should land on the same level. Proficiency describes how well someone performs a skill today; it is separate from whether they hold a certification, how long they have been in the role, or how confident they feel. Everything downstream, from a skills matrix to a succession plan, inherits its accuracy from how well those levels are defined. Why the Scale Matters More Than the Skill List Most organizations spend their energy on the skill list. Which skills, how many, how to group them. The list is the easy part. A list of 300 skills with no levels tells you which words appear in your workforce. It cannot tell you where the depth is, where the risk is, or where to spend a training dollar. Four decisions depend directly on the scale. Assessment. Without levels, an assessment is a yes-or-no checkbox, and a checkbox cannot distinguish the pump-swapper from the manifold diagnostician. With levels, an assessment produces a score that can be compared across people, teams, and time. Gap analysis. A gap is the difference between the level a role requires and the level a person holds. That arithmetic is only possible if both sides are expressed on the same scale. Gap analysis without proficiency levels is an opinion survey. Succession and staffing. "Ready now" versus "ready in 18 months" is a statement about proficiency on a defined set of skills. A resource planner staffing a data center commissioning project needs to know who is at level 4 on power distribution, not who has the phrase on their profile. Learning design. The move from level 2 to level 3 on a skill is a specific development target with a specific set of activities. "Get better at hydraulics" is not. The Common Scales, Compared There is no single correct scale. There are several well-established ones, and the right choice depends on how the levels will be used. Scale Levels Best for Watch out for 3-level (Basic, Proficient, Expert) 3 Compliance and frontline roles where the question is "can they do it safely, unsupervised" Too coarse for development planning; most people cluster in the middle 4-level (Awareness, Working, Practitioner, Expert) 4 Professional and knowledge roles; avoids a false midpoint Assessors drift toward level 3 as the default "fine" 5-level, 0–5 (N/A through Expert) 6 including zero General-purpose enterprise use; fine enough for gaps, coarse enough to assess Level 5 gets over-awarded unless it is anchored to "teaches and sets the standard" Dreyfus (Novice, Advanced Beginner, Competent, Proficient, Expert) 5 Roles where judgment under ambiguity matters; clinical, engineering, leadership Anchors are about how people think, which is harder to observe than what they do Career-stage or grade-linked (Associate through Principal) Varies Job architecture and pay banding Conflates tenure and title with capability; a senior title is not a proficiency level The 0–5 scale is the most common in practice because it does three things at once: it allows a true zero, it gives enough range to show progress year over year, and it maps cleanly onto the "meets, exceeds, does not meet" language most managers already use. A 3-level scale is the right answer for a certification gate. A Dreyfus-style scale is the right answer when the skill is mostly judgment. The mistake is running different scales on different skills inside the same framework. If welding is scored 1 to 3 and project management is scored 0 to 5, no gap report can compare them and no dashboard can roll them up. A Worked Example: Root-Cause Analysis on a 0–5 Scale Here is what a properly anchored scale looks like for a single skill. The skill is root-cause analysis, common to maintenance, quality, IT operations, and clinical safety. The anchors describe behavior, not adjectives. Level Label Behavioral anchor 0 N/A Has not performed or been trained on structured root-cause analysis. 1 Awareness Can describe the purpose of root-cause analysis and name at least one method, such as 5 Whys or fishbone. Has not led or contributed to one. 2 Developing Contributes to a root-cause investigation on routine failures under direction. Gathers evidence and proposes candidate causes but relies on a senior to structure the analysis and confirm the conclusion. 3 Competent Independently leads root-cause analysis on known failure types. Selects an appropriate method, separates symptoms from causes, documents evidence, and proposes a corrective action that addresses the cause rather than the symptom. 4 Advanced Leads analysis on novel or intermittent failures with incomplete data. Designs tests to confirm or eliminate causes, coordinates across functions, and validates that corrective actions eliminated recurrence. 5 Expert Sets the organization's method and standard for root-cause analysis. Coaches others to level 3 and above, reviews investigations for rigor, and identifies systemic patterns across multiple incidents. Read the anchors again and notice what is missing. There are no years of experience. There is no reference to certification. There are no words like "strong" or "good." Every anchor answers the question an assessor actually needs answered: what would I see this person do? A maintenance role might require level 3. A reliability engineer role might require level 4. A quality manager might require level 5 on this one skill and level 2 on a dozen others. The scale is shared; the requirements vary by role. How to Define Proficiency Levels for a Skill Building anchors like the ones above is a repeatable process. Six steps, applied to one skill at a time. Name the skill narrowly. "Hydraulics" is not a skill; it is a subject. "Hydraulic system fault diagnosis" is a skill. If you cannot picture a person performing it, the name is too broad to scale. Define the top and the bottom first. Write the anchor for the highest level you will ever need, then for level zero. The top level is usually "sets the standard and develops others," and the bottom is "no exposure." Everything else sits between two fixed points. Describe the middle as a change in conditions, not effort. The move from level 2 to level 3 is almost always a shift from "with guidance" to "independently," and from "routine cases" to "unfamiliar cases." Level 4 adds "novel situations, incomplete information, cross-functional." Write the anchors around those variables. Test each anchor against three real people. Pick someone you would place at level 2, 3, and 4 today. Read them the anchors without the numbers. If they cannot place themselves, or if two managers place them differently, the anchors are still adjectives in disguise. Attach evidence expectations. For each level, note what an assessor would accept as proof: an observed task, a work sample, a supervisor attestation, a certification, a test score. This is what separates a scale you can audit from a scale you can only vote on. Set the required level per role, separately. The scale describes the skill. Requirements describe the role. Keep them apart. A single skill will have different required levels across the ten roles that use it, and those requirements will change more often than the scale does. Applied to the root-cause example: a manufacturing plant defined the skill, wrote levels 5 and 0, built the middle around "routine versus novel" and "directed versus independent," then tested the anchors on a reliability engineer, a senior technician, and a new hire. The engineer placed herself at 4, both her managers agreed, and the anchors held. It took one afternoon. Proficiency, Competency, and Skill The three terms overlap enough that frameworks routinely confuse them. A skill is the ability to perform a specific activity. A competency is the bundle of skills, knowledge, and behaviors a role requires. Proficiency is the measured level of performance on a skill, and by extension on a competency when the component skills are rolled up. So a technician has the skill "hydraulic fault diagnosis" at proficiency level 3, which contributes to the competency "equipment reliability" that her role requires at level 3 overall. Proficiency is the number. The skill is what the number is attached to. The competency is what the role cares about. The longer version of this distinction, with more examples, is in skills vs. competencies . The practical consequence: proficiency levels belong on skills, not on competencies. Score the parts and roll up. Scoring the whole directly produces a number nobody can act on. Using Levels in a Skills Matrix and in Assessment Once every skill has a scale and every role has required levels, two tools become possible. The first is the skills matrix. Rows are people, columns are skills, cells are proficiency levels, and the color of the cell is the gap against the role requirement. A matrix without levels is a grid of checkmarks. A matrix with levels is a heat map of where the organization is thin, where it is deep, and who is one step from ready on the skills that matter. The mechanics are in the skills matrix guide . The second is assessment. With behavioral anchors in place, an assessment stops being a satisfaction survey and becomes a structured judgment against a standard. Self-assessment gives one view. Manager assessment gives another. Observed task performance or a work sample gives the one that holds up under audit. A proficiency assessment built on anchored levels lets those views be compared, and the gaps between self and manager ratings are themselves useful data. Four Ways Proficiency Scales Go Wrong Too many levels. A 10-point scale feels precise and assesses like noise. Nobody can articulate the difference between a 6 and a 7. Five or six levels including zero is the ceiling for most skills. Unanchored levels. A scale that reads "1 = Beginner, 2 = Intermediate, 3 = Advanced" has defined nothing. Each assessor brings their own meaning of intermediate. The whole point of the scale is to remove that variance. Self-rating only. People are unreliable narrators of their own proficiency in both directions. Experts underrate themselves; novices overrate themselves. Self-assessment is a useful starting signal and a poor final record. Pair it with manager or observed assessment before treating the number as true. Confusing tenure with proficiency. Fifteen years on the job is not level 5. Some people plateau at level 3 for a career. Some reach level 4 in three years. Grade-linked scales bake this confusion in, which is why job level and proficiency level should be tracked as separate things. A Scale Is a Shared Language The technical purpose of a proficiency scale is measurement. The organizational purpose is agreement. When a shift supervisor in one plant and a training manager in another both say "level 3 on fault diagnosis," they mean the same thing, and a person can move between those plants with their capability intact and legible. That shared language is what lets skills data travel: from an assessment into a gap report, from a gap report into a development plan, from a development plan into a staffing decision, from a staffing decision into a succession plan. None of those handoffs work if the number means something different at each step. So the scale is not really a score. It is the grammar that makes everything else about workforce capability sayable. Define it carefully, once, and the rest of the system can finally speak in complete sentences. FAQ What does proficiency mean in a skills context? Proficiency is the measured level of performance a person demonstrates on a specific skill today. It is separate from certification, tenure, or self-confidence, and it is expressed on a defined scale with behavioral descriptions at each level. What are the standard proficiency levels? The most common scale runs from 0 to 5: N/A, awareness, developing, competent, advanced, and expert. Three-level and four-level scales are also common, and the Dreyfus model uses novice through expert. The scale matters less than having behavioral anchors at each level. What is a skill level scale? A skill level scale is the set of ordered proficiency levels used to rate a skill, together with the anchor descriptions that define what each level looks like in practice. One scale should be applied consistently across all skills in a framework so gaps can be compared. How many proficiency levels should a scale have? Five or six levels including zero is the practical ceiling. Fewer than three makes development planning impossible; more than six produces distinctions assessors cannot reliably make. What is the difference between proficiency and competency? Competency is the bundle of skills, knowledge, and behaviors a role requires. Proficiency is the measured level of performance on a specific skill. Proficiency levels are assigned to skills and rolled up to competencies, not scored on competencies directly. How do you assess someone's proficiency level? Compare observed behavior against the anchor descriptions for each level, using evidence such as observed tasks, work samples, supervisor attestation, or test results. Self-assessment is a useful first signal but should be confirmed by a manager or observed assessment before the level is treated as a record. --- ## What Are Skills? Types, Skill Sets, and How Organizations Map Them URL: https://skillsdb.com/blog/what-are-skills-types-and-skill-sets Ask a plant manager what skills their maintenance crew has and you'll get a list of people. Ask the HR system and you'll get a list of job titles. Ask the LMS and you'll get a list of courses completed. None of those is a list of skills. This is the quiet problem underneath most workforce initiatives: everyone uses the word, and almost nobody in the building is working from the same definition. Quick reference: What Is a Skill? — the short version of this post, with the one table that matters. That matters more than it sounds. Recruiting, training budgets, succession plans, and staffing decisions all rest on an implicit model of what people can do. When the model is fuzzy, every decision built on it is fuzzy too. So before anything else, it's worth getting precise about the base unit. What Is a Skill? A skill is a demonstrable ability to perform a specific task or activity to a defined standard. Three parts of that sentence carry the weight. Demonstrable means it can be observed or tested, not just claimed. Specific means it names an activity narrow enough to assess: "configure a VLAN on a Cisco switch," not "networking." Defined standard means there is a level of performance the skill can be measured against, which is what makes proficiency possible. A skill is distinct from knowledge (knowing how a VLAN works), from an ability (the underlying capacity to reason about networks), and from a competency (the bundle of skills, knowledge, and behaviors a role requires). Skills are acquired through practice, they can be assessed independently of the person's job title, and many of them decay without use. That last point is the one most systems ignore, and it is why "trained" and "currently skilled" are not the same thing. Everything else in workforce planning is built on top of this unit. Get it right and the rest of the model becomes tractable. Skills, Competencies, Knowledge, and Abilities These four words get used interchangeably, and the confusion has real costs when they end up as columns in the same spreadsheet. Knowledge is what someone understands. A nurse knows the pharmacology of anticoagulants. Knowledge is testable with questions and it does not by itself produce a result. Ability is the underlying capacity to do something. Spatial reasoning, working memory, manual dexterity. Abilities are relatively stable, hard to train quickly, and mostly the domain of selection rather than development. Skill is the applied, practiced execution. The nurse titrating a heparin drip correctly at the bedside is exercising a skill. It draws on knowledge and ability but is neither. Competency is the bundle a role requires: the skills, the knowledge, and the observable behaviors that together produce acceptable performance in a job. "Medication management" is a competency. It contains a dozen skills. The practical rule: skills are what you assess and develop. Competencies are what you attach to roles. If you build the framework the other way around, you end up assessing things too broad to score and developing things too vague to train. The full distinction, with examples, is in skills vs. competencies . The Types of Skills Taxonomies of skill types vary, but four distinctions do most of the work in practice. Hard skills and technical skills Hard skills are teachable, measurable, and usually specific to a domain or tool. Welding to a code standard. Writing SQL. Reading a P&ID diagram. Operating a forklift. Technical skills are the subset tied to a particular technology, method, or system. They are the easiest skills to define, the easiest to assess with a test or observation, and the ones most likely to have a formal certification behind them. They are also the skills most likely to go stale. A technical skill on a system that changes every 18 months has an 18-month half-life whether the training record says so or not. Soft skills and behavioral skills Soft skills are the interpersonal and cognitive skills that shape how work gets done: communication, prioritization, conflict handling, coaching. The term undersells them. In most roles they determine whether the hard skills produce value. A brilliant engineer who cannot explain a root cause to a non-engineer produces less than a competent one who can. Behavioral skills are the observable, situation-specific version of soft skills, and the version worth assessing. "Communication" is not assessable. "Delivers a clear shift handover covering open issues, risks, and owners in under five minutes" is. The move from soft skill to behavioral skill is mostly a matter of writing down what good looks like. Transferable skills Transferable skills move with the person across roles, functions, and industries. Structured problem solving. Data literacy. Project coordination. Stakeholder management. They are the skills that make internal mobility possible, and the ones most organizations fail to record because no single job description owns them. An organization that tracks transferable skills can see that the customer support lead who ran the CRM migration has 60% of what the junior product manager role needs. One that tracks only job titles sees a support lead. Durable skills and perishable skills This is the distinction most frameworks miss entirely. Durable skills hold their value across years and technology cycles: analytical reasoning, writing, negotiation. Perishable skills degrade without practice or become obsolete as tools change: a specific software version, a procedure that gets revised, a regulatory process that changes annually. The distinction changes how you manage them. Durable skills need to be developed once and refreshed rarely. Perishable skills need currency tracking, recertification triggers, and a decay model. Treating both the same way, as a checkbox that stays checked forever, is how a workforce ends up with a qualified-on-paper crew that cannot actually perform. There is a longer treatment in durable vs. perishable skill sets . What Is a Skill Set? A skill set is the combination of skills a person holds or a role requires, grouped so that it describes a coherent capability. Individuals have skill sets. Roles have required skill sets. The gap between the two is where every development plan starts. A useful skill set is specific enough to assess and complete enough to describe the work. Three worked examples show what that looks like. Data center technician Skill Type Typical required level (0–5) Rack and cable installation to site standard Hard / technical 4 Power distribution fault isolation Hard / technical 3 Cooling system monitoring and alarm response Hard / technical 3 Change ticket documentation Behavioral 3 Escalation communication under incident conditions Behavioral 3 Vendor certification maintenance (e.g., CDCP-type credentials) Perishable Current Half of this skill set is perishable. A technician who was excellent on the previous generation of power distribution units and has not touched the new ones is not a level 3 today, regardless of what a two-year-old record says. Project manager Skill Type Typical required level (0–5) Scope definition and change control Transferable 4 Schedule development and critical path analysis Hard 4 Risk identification and mitigation planning Transferable 3 Stakeholder expectation management Behavioral 4 Budget tracking and variance reporting Hard 3 Facilitation of decision meetings Behavioral 3 Almost nothing here is perishable, and most of it is transferable. That is why project managers move across industries more easily than most roles, and why a skills-based system can spot a strong internal candidate in a function the job description never mentioned. Registered nurse, acute care Skill Type Typical required level (0–5) Patient assessment and early deterioration recognition Hard / clinical 4 Medication administration and reconciliation Hard / clinical 4 Electronic health record documentation Technical 3 Handover communication (SBAR or equivalent) Behavioral 4 De-escalation with patients and families Behavioral 3 Unit-specific equipment operation Perishable Current Clinical skill sets mix everything: durable clinical judgment, perishable equipment competence, behavioral communication, and formal licensure. This is why healthcare has invested more in competency architecture than most industries. The cost of a stale record is measured in patient outcomes. How Skills Are Measured Naming a skill is the first half. The second half is a scale. Without one, "has SQL" means anything from "wrote a SELECT statement once" to "tunes production query plans." Proficiency levels solve this by attaching a defined standard to each level of a skill, usually on a 0–5 or similar scale, with a behavioral description of what each level looks like. Level 2 in root-cause analysis might read "identifies probable causes for routine failures with guidance." Level 4 might read "leads structured analysis on novel failures and validates corrective actions." The difference between the two is assessable, and the gap between where someone is and where the role needs them is a number rather than an impression. The scale is what turns a list of skills into a skills matrix, a gap analysis, or a succession plan. There is a full guide to building one in proficiency levels: scales, examples, and how to define them . How Organizations Map Skills Individual skills, grouped into skill sets, measured on proficiency scales. The remaining question is how an organization holds all of it in one place. The answer is a skills library, sometimes called a skills taxonomy or skills framework. What a skills library is A skills library is the organization's controlled vocabulary of skills: each skill named once, defined once, given a scale once, and then referenced everywhere it matters. Roles point to skills in the library. Assessments score people against skills in the library. Learning content is tagged with the skills in the library it develops. Because there is one definition, a gap on the maintenance team and a gap on the operations team mean the same thing and can be compared. Without a library, every manager writes their own version of "troubleshooting," every job description invents a new phrasing, and the organization ends up with 400 skills that are really 80. Why fixed industry taxonomies fail There is a tempting shortcut: license a pre-built taxonomy with 30,000 skills already defined and load it in. It looks impressive in a demo. It rarely survives contact with the organization. The reason is that no two organizations define competence the same way, and the definitions that stick are written in the organization's own language, mapped to its own roles and standards. A generic "Electrical Troubleshooting" skill with a generic description does not tell a technician at a specific plant what level 3 means on their equipment against their procedures. So managers ignore it, assessments drift back to gut feel, and the taxonomy becomes shelfware. The libraries that work are built from the organization's roles outward: start with the 20 roles that matter most, define the skills those roles actually require in the words the people doing the work would use, attach scales with behavioral anchors, and grow from there. External taxonomies are useful as a reference to borrow from, not as a foundation to adopt. SkillsDB is built around this approach, with a skills library designed to be authored in the customer's language rather than imported from a catalog. A short checklist for a working skills map Every skill has one canonical name and one definition. Every skill has a proficiency scale with behavioral anchors at each level. Every role references its required skills and levels from the library. Perishable skills carry a currency rule: recertification interval, decay trigger, or evidence requirement. Assessments, learning content, and job architecture all reference the same library, so a gap means the same thing everywhere. Someone owns the library. Uncurated skills libraries decay as fast as perishable skills do. The Base Unit Org charts describe reporting lines. Job titles describe what the company decided to call the work. Headcount describes how many people are on payroll. None of them describe what the organization can actually do. Skills do. They are the base unit that every other workforce structure is composed from. A role is a skill set with a title. A team is a set of skill sets with a manager. A succession plan is a prediction about which skill sets will be ready when. A training budget is a bet on which skills will move. When the base unit is undefined, all of that runs on approximation. When it is defined, named, scaled, and held in one place, the approximations become measurements. That is the whole argument for treating skills as infrastructure rather than as a field in an HR record. Define the unit first. Everything else follows. FAQ What is the simplest definition of a skill? A skill is a demonstrable ability to perform a specific task to a defined standard. The three tests are that it can be observed or assessed, that it names an activity narrow enough to score, and that there is a standard of performance to measure it against. What is the difference between a skill and a competency? A skill is a single, assessable ability, such as configuring a network switch. A competency is the bundle of skills, knowledge, and behaviors a role needs to perform acceptably, such as network infrastructure management. Skills are what you assess and develop; competencies are what you attach to roles. What are the main types of skills? The four distinctions that matter most in practice are hard or technical skills versus soft or behavioral skills, and durable skills versus perishable skills. Transferable skills, which carry across roles and industries, cut across those categories and are the foundation of internal mobility. What is a skill set? A skill set is the combination of skills a person holds or a role requires, grouped so that it describes a coherent capability. Comparing an individual's skill set with a role's required skill set is how skills gaps are identified. What is a skills taxonomy or skills library? A skills library is an organization's controlled vocabulary of skills, with each skill defined once and referenced by roles, assessments, and learning content. It is sometimes called a taxonomy or framework. Libraries built in the organization's own language and mapped to its own roles are far more likely to be adopted than generic licensed taxonomies. How are skills measured? Skills are measured with proficiency levels, usually a scale such as 0 to 5, where each level has a behavioral description of what performance looks like. Assessing a person against that scale produces a proficiency score, and comparing it with the level a role requires produces a measurable gap. --- ## Workforce Strategy Is Capability Planning, Not Headcount Planning URL: https://skillsdb.com/blog/workforce-strategy-capability-planning Sit through any board-level discussion of workforce and listen for the unit of measurement. It's almost always headcount. How many people do we have. How many are we hiring. How many are leaving. How many can we get to a new region by Q3. How many fewer can we run on next year. The CFO does the math in headcount because the budget is in headcount, the comp plans are in headcount, and headcount is the variable that fits cleanly on a spreadsheet. The problem is that headcount is the wrong unit for the decision being made. The board doesn't actually want to know how many people the company has. The board wants to know whether the company can execute next year's strategy — launch the new product line, enter the new market, integrate the acquisition, ship the platform rebuild. Those questions can't be answered in headcount. They can only be answered in capability. The shift from one to the other is the workforce strategy conversation worth having in 2026. The Default Architecture (and why it produces the wrong answer) The default workforce planning architecture has three layers, and each one operates in headcount. Layer one: the HRIS. Records who works here, what they cost, when they were hired, who they report to. Headcount, in different cuts. Layer two: the budget model. Approved positions, vacant positions, hiring plan, attrition forecast. Headcount, projected forward. Layer three: the strategic plan. The five priorities for the year, the geographic expansions, the product launches, the customer commitments. Capability, implicitly. Translated to headcount at the last minute because that's the unit the budget model speaks. The translation is where everything falls apart. The strategic plan says "launch the new platform." The budget model says "hire 12 engineers." The HRIS says "we have 138 engineers already." The board approves. Twelve hires happen over six months. The launch slips by a quarter because the actual capability needed — distributed-systems engineering at senior+ level with experience in the specific domain — wasn't 12 generic engineers. It was four very specific ones. The other 138 engineers couldn't fill the gap because the gap was never visible in headcount terms. The workforce plan delivered the headcount it was asked for. The strategy it was supposed to support didn't ship. This pattern repeats every quarter, in every company that runs strategic planning in capability terms but workforce planning in headcount terms. The gap between the two is where strategic execution lives or dies. What Capability Planning Actually Looks Like The shift is small to describe and structurally large in effect. Workforce planning starts with the strategic capabilities the business needs, not with the headcount budget. The conversation becomes: to launch the new platform, we need 22 person-years of distributed-systems engineering capability, of which 8 person-years need to be senior+ with prior experience in payments infrastructure. That's a capability statement. It can be matched against assessed proficiency in the workforce — we have 5.5 person-years of that capability today, distributed across 3 senior engineers; the gap is 16.5 person-years, of which 2.5 person-years need to be senior+. That gap is the workforce ask. The headcount that follows from that capability gap might be 9 engineers, not 12 — because two of the senior engineers were already 50% deployed against other work and can be reprioritized, and because one of the senior-staff engineers in another business unit has the right specialization but wasn't on the strategic plan's radar because no one knew. The headcount is smaller and more specific than the default model would have produced. This is what capability planning looks like in practice. The unit of analysis is capability — a typed, measured, queryable property of the workforce. The headcount is a derived number, calculated against the capability gap rather than negotiated against the budget. What This Requires Architecturally Three pieces have to be in place for capability planning to operate, and most organizations have one or two. A capability inventory. Not a job-title list. A typed inventory of the specific capabilities the business actually competes on, in the business's own language, with proficiency definitions that the operating leaders believe in. This is the work most companies haven't done; the ones that have, did it deliberately over a quarter or two with their practice leaders, not in a vendor workshop. Assessed proficiency, not asserted. For each capability, the workforce has a current proficiency state — assessed, not assumed. Manager and self-assessment against role benchmarks, on a configurable scale, refreshed on a regular cycle. This is the foundation; without it, the rest of the architecture runs on fiction. A capability-to-strategy mapping. When the strategic plan calls for a new capability or more of an existing one, the planning team can quickly model the gap against current state and project forward. This is the calculation that produces the workforce ask in capability terms first, headcount second. Most companies have fragments of this. Few have all three. The CHRO who builds out all three is the one who walks into the next board meeting with a workforce plan that maps cleanly to the strategic plan — not because of better slide work, but because the underlying data model finally fits the question being asked. What Changes in the Board Conversation The two-minute board conversation about workforce shifts in specific ways. Where before the CHRO presented a headcount plan and the board asked whether it was achievable, the conversation becomes: here are the capabilities the strategic plan requires, here's what we have, here's the gap, here's how we close it (some hire, some develop, some redeploy, some external partnership). The board approves a capability plan , with the headcount as a calculated output. The CFO's spreadsheet still rolls up to headcount, but the conversation that drove it was about capability. Three downstream effects follow. Hiring becomes more specific and less expensive. Instead of "we need 12 engineers," it's "we need 4 distributed-systems engineers at senior+ in payments, 3 mid-level frontend with React Native, 2 platform engineers with database-internals experience." Recruiting goes after a smaller, more specific candidate set and closes them faster. Development becomes strategic, not aspirational. Training and learning programs target the capability gaps that show up in the strategic mapping. The L&D budget is spent against gaps the business has committed to closing, not against generic content libraries hoped to be useful. Workforce risk becomes visible. The capabilities where the company has dangerous concentration — three senior people who can do the thing, two of them flight risks — become flagged risk items in the workforce plan, with mitigation strategies that aren't just "hire more of them" but include redundancy through development, knowledge transfer, and acquisition. Where the Bar Should Sit Now CHROs are increasingly asked to speak the language of strategy, and the language of strategy is capability. The ones who do this well don't translate strategy into headcount and present headcount. They present capability — current state, gap, plan to close — and let headcount fall out of the math as a derived number. This is the workforce strategy conversation that earns CHROs a real seat at the strategic planning table, not the operational seat where headcount and comp band issues get adjudicated. The shift requires the underlying data — assessed capability at workforce scale — to exist. Without that, capability planning is a slogan. With it, it's the operating model the next decade of workforce leadership runs on. If your board asks how many people you have and you answer with a number, you've optimized for the wrong conversation. Answer with capability, and the conversation gets shorter, sharper, and substantially more aligned with what the business is actually trying to do. Frequently Asked Questions How is capability planning different from headcount planning? Headcount planning asks "how many people do we have, and how many do we need to add or remove." Capability planning asks "what capabilities does the strategy require, what capabilities do we have, where are the gaps, and how do we close them." Both produce a budget number at the end, but capability planning produces a specific and smaller one because the gap is measured in the unit the strategy actually needs, not in the generic unit the budget speaks. Headcount becomes a derived output, not the starting point. What's a "capability inventory" and how do we build one? A capability inventory is the typed, structured list of the specific capabilities the business competes on — written in the business's own language, with proficiency definitions defined by the operating leaders who actually use them. Building one takes a deliberate quarter or two of conversations with practice leads, function heads, and senior individual contributors. Most companies start with a working draft of 60-120 capabilities for a mid-size workforce, refined over the first assessment cycle. Pre-built taxonomies don't survive contact with the operation; the inventory has to be the organization's own. Doesn't this take a lot of assessment overhead? Less than companies expect. The shift is from doing nothing (with assertion-based skills data, which is the default) to running an assessment cycle quarterly or semi-annually against the capability inventory. Manager-and-self assessment is the workhorse; the platform handles the scheduling, the reminders, and the aggregation. The first cycle is the heaviest because the framework is new; subsequent cycles run in days, not weeks. How does the CFO think about capability planning? The CFO still operates the budget in headcount and comp dollars. What changes is that the workforce ask coming into the budget conversation has a capability rationale behind it. "We need to add $X in payroll for distributed-systems senior+ in payments" is a different ask than "we need 12 more engineers" — more specific, more defensible, and tied directly to the strategic deliverables the board approved. CFOs generally respond well to the specificity once they see the data model behind it. What's the first step for a CHRO who wants to make this shift? Start with one strategic priority. Pick the most important capability ask for the coming year — the new market entry, the platform build, the acquisition integration — and run a capability planning exercise on that one. Define the capabilities required, assess the workforce against them, identify the gap, and model the close. Present the result alongside the headcount plan in the next board cycle. One worked example builds the case for adopting the model across the rest of workforce planning. --- ## Skills Currency vs. Skills Completion: Why "Trained" and "Current" Aren't the Same Word URL: https://skillsdb.com/blog/skills-currency-vs-skills-completion A commercial pilot can hold a 737 type rating and not be legally allowed to fly a 737 today. Type rating says she's trained on the aircraft. Currency says she's flown three takeoffs and landings in the last 90 days. The first is permanent. The second decays. Aviation built its safety architecture around the difference fifty years ago and would never confuse the two. Medicine has the same distinction. Board certification proves the surgeon was once qualified. Active practice — case volume, procedural recency, hospital privileges renewal — proves they're currently competent. The cardiac surgeon who hasn't operated in two years isn't "trained but rusty." She's specifically not current. Hospitals enforce the distinction in credentialing committees. Insurance carriers enforce it in coverage decisions. Patients enforce it the moment they ask "how many of these have you done in the last year." Engineering, nuclear operations, defense, regulated chemistry — every domain where the cost of mistaking trained for current is paid in incidents has built around the difference for decades. HR, until recently, hasn't. Where the Conflation Comes From The default HR architecture treats training as a one-time event. The LMS records completion. The HRIS stores certifications. The skills field, when it exists, gets populated at the moment training finishes and then never updates. Six months later, the system still says the employee can do the thing, and there's nothing inside the system that knows otherwise. This is fine when the underlying skill is genuinely stable — basic literacy, compliance training people are going to forget but won't need to act on for years. It's not fine when the skill is operational and decays. A welder qualified on a specific weld type six years ago and hasn't done it since is treated by the system the same as one who welded a hundred joints last month. The audit signs off on both because the system can't tell them apart. The cost shows up in three places. Workforce visibility lies upward. Leadership pulls a report on "how many people are qualified to do X" and gets a number that includes everyone trained at any point. The actual operational depth — the number of people currently performing or capable of performing X today — is some unknown fraction of that. Workforce planning runs on the inflated number. Compliance findings persist. ISO, FDA, FAA, NRC — every regulated framework that touches workforce competency draws the distinction between qualification and current competence. Auditors find it in the same place every cycle: the company has trained records but can't prove currency. The finding gets a CAPA. The CAPA promises a process. The process doesn't fix the data architecture. The finding recurs next cycle. Strategic capability gets mismeasured. When a CHRO sits in a board meeting and reports on workforce capability, the numbers are functionally inflated by everyone who was trained on something they haven't done since. The capability that actually exists is a smaller, more honest number — and the leaders who learn to operate from that number make better workforce bets than the ones who learn to operate from the optimistic version. What Currency Means as a Skills Primitive Currency isn't a binary. It's a structured property of a skill that captures three dimensions: Recency. When was this skill last assessed, performed, or refreshed? A skill last assessed three years ago has a different operational meaning than one assessed last quarter. Decay rate. How fast does this specific skill lose currency in the absence of practice? Compliance knowledge decays slowly. Specialized procedural skills decay fast. Tool-specific software skills decay in proportion to how much the tool itself has changed. Re-currency conditions. What does it take to restore currency? Sometimes assessment alone. Sometimes practice plus assessment. Sometimes a structured retraining and a supervised session. A skills system that treats currency as a first-class property — with decay rates configured per skill, recency tracking attached to every qualification, and re-currency conditions defined for each one — produces a different operational picture than the default LMS-plus-HRIS architecture. The workforce-capability report stops being "everyone who's ever been trained on this." It becomes "everyone who is currently qualified, plus the ones approaching expiry, plus the ones who've lapsed and would need to re-cert." That's a different number. It's also the number the operation actually runs on. How Currency Changes the Decisions A few decisions shift when the system can tell trained from current. Staffing. Resource managers staffing a project don't pull from "everyone trained on X." They pull from "everyone currently qualified on X, in the right time zone, available 50%+ next month." The shortlist is smaller and more accurate. The match is operational, not theoretical. Workforce planning. Capacity models stop being inflated by people who hold lapsed qualifications. Hiring decisions get sharper because the gap is real. Retention decisions get sharper because the cost of losing a currently-qualified employee is visible — that person is rare, not interchangeable with anyone who once attended the training module. Compliance. The audit answer stops being a retrospective excavation and becomes a current-state query. "Show me everyone currently qualified against revision 4 of SOP-12, with assessment evidence in the last 12 months." The system either has it or it doesn't, and the answer is the same whether the auditor asks today or six months from now. Career development. The conversation with the employee changes too. "You're trained on X but your currency has lapsed; here's the path to restore it" is a real growth conversation. "You're trained on X" with no currency framing is a record-keeping artifact that doesn't help anyone develop. What This Requires Architecturally Currency-aware skills tracking isn't a feature bolted on top of a completion-tracking system. It's a different data model. Each skill carries decay-rate metadata. Each assessment carries a timestamp the system can age. Each qualification carries expiry conditions configurable by the operation, not assumed by the vendor. The audit log tracks currency events — when someone moved from current to lapsed, when they re-acquired currency, when the underlying SOP revised and re-currency became required. This is the architectural reason why a certification tracking system built on completion records will never produce the answers regulated industries actually need. The data model assumes the wrong primitive. Completion is a moment; currency is a state that has to be maintained. Talent development decisions, frontline training decisions, and workforce strategy decisions all eventually run into the same wall: you can't manage what you can't currently see. Currency is what makes the visibility honest. What the Bar Should Look Like Aviation built its safety record on the discipline of distinguishing trained from current. Medicine built its credentialing systems on the same discipline. Engineering, nuclear, and defense the same. HR has the chance to import a fifty-year-old idea from industries where the cost of getting it wrong is measured in lives. The companies that adopt currency as a first-class skills primitive will run their workforce off honest numbers. The ones that don't will keep reporting capability they can't actually operate on, and learning the gap the hard way every audit cycle. The fix isn't more training. It's a system that knows when training has expired. Frequently Asked Questions What's the practical difference between a "trained" employee and a "current" employee? A trained employee has, at some point, met the qualification standard for a skill or competency. A current employee meets the standard today , with recent enough assessment or practice to demonstrate continued capability. Aviation captures the difference in pilot certification and recency requirements; medicine captures it in board certification versus active practice. The same distinction matters in any operational context where skills decay between use — manufacturing operations, regulated chemistry, specialized engineering, software practice on changing tools. Why does this matter more in 2026 than it did five years ago? Two things shifted. First, regulators across multiple industries (FDA medical device, FAA, NRC, ISO 13485) have sharpened expectations around competence currency — auditors now ask the recency question explicitly rather than accepting historical completion records. Second, workforce planning has moved from headcount to capability, and capability is materially overstated when lapsed qualifications get counted as current. Both forces push toward systems that track currency natively. Does this require running assessments more often? Sometimes, but not always. Currency is configurable per skill — some skills decay slowly enough that annual assessment is sufficient; some require quarterly or monthly verification depending on regulatory framework or operational risk. The shift isn't "assess everyone, more often." It's "assess each skill on a cycle that matches its actual decay characteristics, and let the system maintain the currency state." How does a certification tracking system handle currency differently than a training tracking system? A training tracking system records completion: the employee went through the training, and the record stands forever. A currency-aware certification tracking system records the same completion but layers expiry rules, re-certification triggers, and decay-rate metadata on top. When the certification approaches expiry, the system flags it. When the underlying SOP revises, the system flags affected qualifications. The currency state — not just the completion record — is what the operation runs against. What's the first step for a company that wants to adopt currency-based skills tracking? Inventory the skills where decay actually matters. For most companies, this is a tractable subset of the full skills catalog — high-decay skills in regulated environments, tool-specific skills where the tool changes, procedural skills tied to revision-controlled documents. Define decay rates and re-currency conditions for that subset first; expand from there. Trying to retrofit currency across the entire skills catalog at once is what stalls the initiative. Starting with the 20% of skills where currency actually drives decisions delivers the operational value in a single cycle. --- ## Why Your Engagement Survey is Disconnected From Every Talent Decision You Make URL: https://skillsdb.com/blog/engagement-survey-disconnected-from-talent-decisions The annual engagement survey runs in March. Forty questions, fifteen demographic cuts, a board-deck readout in May, a senior leadership debrief in June. The "engagement score" moves three points, plus or minus. The slide deck goes into a shared drive. Mid-year reviews start, performance cycles spin up, succession plans get refreshed. None of those conversations references the survey results. This is the silent pattern in most engagement programs. The survey collects real signal — what employees are frustrated by, what would make them stay, what would make them leave — and routes it into a PDF that nobody opens during the talent decisions the signal was supposed to inform. The diagnosis isn't survey fatigue or bad questions. It's architecture. The survey is collecting data the rest of the talent system can't read. Where the Disconnect Lives Sit through a senior leadership debrief on engagement results and listen for one specific moment. Someone will say "people in engineering are frustrated with career growth." The room will nod. The slide will move on. And nothing will change in how engineering's career frameworks, learning plans, succession pipelines, or internal mobility programs operate over the next twelve months. The reason isn't a lack of care. It's that the survey data and the talent decision systems live in entirely separate places. The survey result is a percentage on a slide. The career framework is a document in another tool. The learning plans are inside the LMS. The succession plan lives in HRIS or a spreadsheet. None of them reads from the survey. None of them updates because of it. So even when leadership knows engineering is frustrated about growth, nothing structural happens. A workshop gets scheduled. A "career conversations toolkit" gets sent out. Three months later the underlying issue is unchanged because none of the operational systems that govern growth changed. Engagement survey results die in PDFs because the talent system isn't architected to consume them. Three Things Companies Conflate (and what each one is actually for) A lot of the dysfunction in this space comes from confusing three different tools that look similar from a distance. Assessments measure capability. What can this person actually do, against a defined competency, at what proficiency level. Manager-and-self, against role benchmarks. The output is a proficiency score and a gap analysis. The decisions assessments inform: learning plans, succession readiness, promotion thresholds, staffing decisions. Surveys measure perception. How does this person feel about something — their work, their manager, their growth path, their team. The output is sentiment data, themes, and free-text signal. The decisions surveys inform: management training priorities, organizational design changes, policy adjustments, communication strategy. Pulse checks measure trend. Is sentiment moving in the right direction, week over week or month over month, against a specific intervention. The output is a trend line. The decisions pulses inform: whether last quarter's change worked, whether the org is responding to a leadership transition, whether the team that just lost a manager is recovering. These tools serve different jobs. The mistake companies make is running one tool and expecting it to deliver the others' answers — running an engagement survey and expecting it to tell you about capability, or running an assessment cycle and expecting it to tell you about sentiment. Each tool produces specific evidence; treating them as interchangeable produces decisions that aren't supported by the data underneath them. The CHRO who's clear about which tool answers which question is the one whose talent program runs on evidence. The one who runs them all and treats the output the same way is the one whose program runs on theater. What Changes When Survey Results Connect to the Talent System The fix isn't more surveys, more frequent surveys, or different surveys. The fix is wiring survey output into the talent decision systems so the signal actually moves them. In a connected architecture, the survey-to-action loop looks like this: Survey results map to people and teams , not just aggregate scores. The "career growth frustration in engineering" signal isn't a slide — it's a flagged cohort. Flagged cohorts trigger downstream review. Career framework completeness for the affected roles, learning plan utilization, manager-conversation cadence, internal mobility access — each gets reviewed against the survey signal. Specific interventions get planned and tracked , with their own measurement loop. Career conversations get scheduled. Career pathway visibility gets exposed. Skill-based growth opportunities get matched to the cohort. Each action has an owner and a follow-up window. The next pulse measures movement on the specific issue , not the abstract engagement score. The question isn't "did engagement go up." It's "did the cohort that flagged career growth report a different signal six weeks later." This is the survey-to-action loop. It exists in maybe 15% of mid-to-large organizations, and the companies running it look fundamentally different from the ones running annual surveys into PDFs. Their HR programs respond to signal. Their managers know what their team's sentiment is and what they're doing about it. Their employees see specific things change after they submit feedback, which is the single biggest driver of survey response rates not collapsing year over year. Implementation Principles That Matter A few patterns from companies that get this right: Anonymity by design where it earns trust; identification where it earns action. Engagement surveys generally need anonymity at the individual level to get honest signal. Pulse checks on specific interventions can be identified — the trade-off is faster action loops against a smaller-N read. The dysfunction is when an org runs anonymous surveys and then complains they can't take action on individual cases; that's the trade made up front. Survey questions tied to talent decisions, not to corporate values. "How aligned are you with our values" doesn't drive any decision. "How clear is your next career step" does. The questions worth running are the ones the talent system can act on. One survey calendar, not seven. Engagement, manager 360, exit, onboarding, training feedback, project retrospectives — each has a legitimate purpose. Running them on uncoordinated calendars produces survey fatigue. Running them on a coordinated, integrated platform produces a coherent talent signal. The action plan exists before the survey runs. If leadership can't articulate what they'll do with a given response pattern before the survey opens, the survey shouldn't run. Otherwise you're collecting expectations the system isn't ready to honor — which is how you teach an organization not to bother responding next year. What the Bar Should Look Like The point of an employee survey program isn't engagement score management. It's information flow into the talent decision system that's already operating. When the survey signal connects to skills data, career frameworks, and learning plans , the org starts running on evidence — not on the assumption that good intentions plus a slide deck equals action. Survey tools have gotten dramatically better over the past decade. Survey programs haven't, because the bottleneck was never the collection. It was the architecture downstream of collection. A real survey program is the one whose results show up in the next talent development review, not the one whose PDF gets stored in a shared drive. If your engagement survey scored well last year and the talent decisions made since then would have looked the same if it hadn't run at all, the survey isn't the problem. The architecture around it is. Frequently Asked Questions What's the difference between an employee survey and a skills assessment? A survey measures perception — how an employee feels about their work, their manager, their growth, their team. An assessment measures capability — what the employee can actually do , against a defined competency, at what proficiency level. The two are complementary inputs into talent decisions, but they're not interchangeable. Engagement scores don't tell you about skill gaps; proficiency scores don't tell you whether the team is burnt out. Companies running one and expecting it to deliver the other's evidence end up making decisions on incomplete data. Why do engagement survey response rates drop after the first run? Because employees track whether anything changed after the last survey. When the action plan after a survey is "the slide deck got presented to leadership," the next survey signals that responding is theater. When the action plan after a survey is "career frameworks for engineering got rebuilt, learning plans got rewired against the gaps employees flagged, and pulses ran six weeks later to measure movement," the next survey signals that responding moves the organization. Response rates track that signal precisely. How do you actually tie engagement survey results to talent decisions? The shift is from aggregate-score reporting to cohort-level signal that downstream systems can read. Survey results map to specific teams, roles, and functions. Flagged cohorts trigger automatic reviews of the relevant talent system — career framework completeness, learning plan utilization, manager conversation cadence, internal mobility access. Each flagged area gets a specific intervention with an owner, a timeline, and a follow-up pulse measuring movement on the specific issue. The architecture is what carries the signal — not the survey itself. Should pulse surveys be anonymous? Depends on the question they're answering. Pulses measuring trend on broad sentiment (is the org recovering after a leadership transition, are we drifting on engagement) generally need anonymity to get honest signal. Pulses measuring response to a specific intervention (did the new career framework actually help the engineering team that flagged frustration) can be identified — the trade-off is faster, more specific action loops against a smaller honest-response window. Most healthy programs run both, on different cadences, for different decisions. What's a "survey-to-action loop" and how is it different from a typical survey program? A survey-to-action loop is an architected pattern: every survey question is tied to a specific talent decision or downstream system, every cohort signal triggers a defined review, every intervention has a follow-up pulse measuring movement. A typical survey program collects responses, scores them, and reports the aggregate to leadership. The first one drives change; the second one drives reporting cycles. The difference is structural — it's whether the talent system is architected to read survey output, or whether the survey output is architected to fit a slide deck. --- ## Resource Planning From a Skills Database, Not a Resume Spreadsheet: Where Services Firms Find Their Hidden Bench URL: https://skillsdb.com/blog/resource-planning-skills-database The single most expensive sentence inside a professional services firm is "we don't have anyone available with that experience." It gets said in staffing meetings, in proposal reviews, in week-ahead resource calls. It usually means one of two things: the people who could do the work are already on other projects, or the people who could do the work aren't visible to the person doing the staffing. The first one is a real constraint. The second one is a data problem masquerading as a capacity problem — and in almost every services firm we've watched at scale, the second one is two to three times more common than anyone realizes. This post is about that second problem. What it costs, why it persists, and what changes when staffing decisions read from a real skills database instead of a stack of resumes. Why Resumes Don't Work as a Planning Artifact Resumes are sales documents. They were written to win the job the consultant already has, not to be a source of truth for what that consultant can do five years later. The skills section is whatever sounded right at hiring, padded with the buzzwords of the year. The project history was edited for impact, not for accuracy. And the document has been updated approximately zero times since onboarding. Layer on the operational reality of a services firm: people grow, skills shift, certifications expire, deep specialization develops on projects nobody outside the project team saw. Two years after hire, the resume in the ATS bears about a 60% resemblance to what the consultant can actually do today. After four years, it's effectively a historical document. This is what resource managers are staffing from. A document that was a sales pitch when it was written and is fiction now. The result is predictable. Project A staffs the consultants the staffing manager remembers . Project B finds the same six experts the firm always pulls for that kind of work. Meanwhile, on the bench, somewhere between 100 and 250 consultants are sitting with capabilities nobody is matching to demand — because the system the staffing decision is being made from can't see those capabilities. The Bench Economics Math Take a mid-size services firm: 1,200 billable consultants, $200K average loaded cost, 75% target utilization. The financial model assumes everyone is either on a billable project or actively being repositioned for one. Reality is messier: at any given week, 12-18% of the workforce is either on the bench, partially utilized, or staffed on work below their skill level. In a firm where staffing reads from resumes plus memory, that bench is mostly invisible to the people making project decisions. Three patterns emerge: Bench drag. Consultants sitting between projects, eating fully-loaded cost while their actual capabilities go unmatched to the deals closing this quarter. A 1,200-person firm sitting at the conservative end of the bench range — 12% — is carrying 144 consultants on bench. At $200K loaded cost, that's $28.8M annual cost; at the realistic 15% no-resume-could-find-them rate, that's $4.3M annually in hidden bench drag. Skill mismatch. Consultants staffed at 80-90% utilization on work that's two competency bands below their assessed capability. The hours are billable. The margin is fine on paper. The strategic cost is two-fold: the senior consultant disengages and leaves within 18 months, and the work the firm could have won with their actual capability never gets pursued. Lost-deal cost. Deals walked away from in pursuit because the firm "didn't have anyone available" — when, in fact, three qualified consultants were on partial utilization and another four were in the wrong city but available remotely. The firm never knows the deal it didn't pursue. Total quantifiable cost for a 1,200-person firm runs $2-3M per year in hidden capacity. Total unquantified cost — talent attrition from misaligned staffing, missed pipeline expansion, recurring rehire on the same competencies the firm already has internally — is multiples of that. This isn't a hypothetical. It's the operational pattern across services firms in the $100M-$500M range. The firms that fix it don't add headcount; they make existing headcount visible. What Changes When Staffing Reads from an Assessed Skills Database The architectural shift is small to describe and structurally large in effect. Resumes are replaced as the staffing source by a skills database where every consultant has assessed proficiency against the competency framework the firm runs on. Manager assessment plus self-assessment plus benchmark validation. Stored as evidence, current, and queryable. When the staffing manager searches for "Series A SaaS pricing strategy experience, conversational French, available 50%+ for the next eight weeks, mid-Atlantic time zone preferred" — the system returns the consultants who actually match, in proficiency order. Not the ones the staffing manager remembers. Not the ones whose resumes happen to contain the right keywords. The ones whose assessed capability fits the work. Three operational changes follow: Bench shrinks because the bench is finally findable. The 15% of capacity that was hidden becomes visible. Project leads start pulling from a population they didn't know they had. Bench drag drops materially within two staffing cycles. Staffing matches improve. Consultants get placed against work that matches their actual capability — not their resume keywords, not the staffing manager's memory. Senior consultants stop being staffed on work that bores them. The first-year attrition number that's been creeping up for three years stops creeping. Pursuit decisions change. When the resource manager can answer "do we have capability for this" with assessed data in five minutes, the firm pursues deals it would have walked away from. Pipeline expansion becomes a function of internal capability visibility, not of optimistic hope. The Shift in the Operational Rhythm The most underrated effect of moving from resumes to a skills database is what happens to the weekly staffing meeting itself. In the resume-driven model, the meeting is a negotiation. Project leads pitch the people they want, the resource manager tries to balance demand, and the unspoken default is to surface the same go-to consultants for the same kinds of work because that's who everyone trusts to deliver. Hours of leadership time go into a conversation that's substantially the same as last week's. In the skills-database-driven model, the meeting becomes a review. The system surfaces the matches. The conversation focuses on the exceptions and the strategic plays — should this junior consultant get a stretch role on this project; which deal pursuits are bottlenecked on a single capability gap; where is the team developing new specialization fastest. Hours of capacity get returned to the people doing the work, and the staffing decisions improve because they're being made from data instead of inertia. This is the unlock services-firm operators talk about once they've seen it. It's not the bench savings, though those are real. It's that the rhythm of running the firm changes. Where This Starts The starting point is the competency framework — the inventory of capabilities the firm actually competes on, in the firm's own language, with proficiency definitions that the practice leads believe in. Most services firms have fragments of this in service-line wikis, project case studies, and partners' heads. The shift is making it a single, structured, assessed source of truth. From there, the assessment cycle begins — manager-and-self, against role benchmarks, on a configurable scale, stored as evidence. After the first full cycle, the staffing meeting starts running off the data. After three cycles, the firm has historical movement: who's developing in which direction, where capability is concentrating, where the next investment in hiring or training should go. The eighteen-month firms that go through this shift end up with a different operating model — not because they bought new software, but because they made visible what they already had. If you're running resource planning off resumes today and the staffing meeting feels like negotiation more than analysis, the math at the top of this post is the cost. The visibility is the answer. Frequently Asked Questions What's the difference between a resource management tool and a skills database? A resource management tool tracks who's on what project — allocations, utilization, billable hours, time off. Necessary but downstream. A skills database tracks what each person can actually do — assessed proficiency, current certifications, capability against role benchmarks, gap to where the firm needs more depth. The resource management tool tells you who's available . The skills database tells you who's qualified . Together they answer the staffing question. Apart, they don't. Why don't resume search and AI inference solve this? Both work from the wrong data. Resume search reads documents written to win interviews five years ago. AI inference scrapes activity signals — LinkedIn updates, project descriptions, task history — and infers skills probabilistically. Inference at 70% accuracy across 1,200 consultants produces a lot of confidently-wrong matches. Assessed proficiency is the floor. Inference can layer on top of it; it can't replace it. How long does it take to stand up an assessed skills database for a services firm? The methodology is the variable, not the platform. Firms that have a working competency framework get to a live assessed database in 90-120 days for a 1,000-person firm. Firms starting from scratch on the framework take a quarter longer — the platform work is fast; the language work (what does "strategy consulting senior" actually mean here?) is what takes deliberate cycles with practice leads. Does this replace the partner's intuition in staffing? No. Partner intuition is a real signal — chemistry with the client, prior project context, judgment calls about stretch versus safety. The skills database changes the baseline the intuition runs on. Instead of partners holding the entire visibility burden in their heads, they make calls against a surfaced shortlist of capability-matched consultants. The intuition gets sharper because it's applied to better candidates. What's the first measurable signal that the shift is working? Bench composition. Within two staffing cycles after live assessment data starts feeding the staffing meeting, the bench mix shifts — fewer consultants sitting passively, more partially-utilized, more strategic-stretch assignments. The hidden 15% becomes findable. The financial impact lags by a quarter; the operational signal shows up first. --- ## Making Engineering Skills Visible on the Factory Floor — Without Adding Another Process URL: https://skillsdb.com/blog/engineering-skills-visible-factory-floor Walk a manufacturing floor with a quality manager and ask one question: which of your operators is currently qualified to run cell 4 on the day shift, and against which revision of the work instruction? You'll get one of three answers. The first is fast and confident, from a manager who's been on this line for fifteen years and carries the answer in his head. The second is let me check the spreadsheet . The third is I can find out by Friday. All three answers are a problem. Not because the people running the floor are doing anything wrong — they're often the most rigorous workforce operators in the building. The problem is that the system around them treats skills as a side artifact, not as the operational reality the line runs on. This is what's broken in manufacturing skills intelligence, and it's what changes when skills become visible at the work-cell level. No new process. Same shop floor. Different visibility. Where Most Manufacturing Skill Programs Fail The default skills system in industrial environments is a spreadsheet that lives somewhere between the training coordinator and the quality manager. Columns are operators, rows are work cells or processes, cells are filled with check marks, dates, or initials. It works at small scale and breaks the moment the line ages, the SOP revises, the workforce churns, or the auditor walks in. Three patterns repeat across the manufacturers I've watched over the past eighteen years. Training completion gets measured. Competency doesn't. The LMS or training tracker can prove the operator sat through the qualification module. It cannot prove the operator can actually run the cell to spec. The two are correlated, not equal — and the gap between them is where quality escapes and audit findings live. Revisions silently invalidate everyone. The SOP for cell 4 gets revised. Forty-two operators were trained against the previous version. The training system carries forward their qualified status as if nothing changed. The quality system flags a deviation six weeks later and the root cause turns out to be that nobody re-trained against the new version because nobody knew to. The data lives in heads. The shift supervisor knows which of his people he trusts on which line. He probably knows it better than any system. But he leaves for a competitor, retires, or gets promoted, and the knowledge walks out with him. The replacement starts from zero and the visibility regresses by years. The common failure is the same: the floor runs on what people can actually do , but the system around the floor stores what people were once trained on . Those are different facts. Acting like they're the same is what makes the spreadsheet feel necessary in the first place. What Changes When Skills Become Visible at the Work-Cell Level The pattern across the manufacturers who got this right is not that they added another process. It's that they took the visibility that already lived in the shift supervisor's head and made it operational. A real competency matrix at the work-cell level does four things the spreadsheet never did: Resolves identity across systems. The operator's training record, certification status, current-revision qualifications, and shift assignment are all keyed to the same person, not three lookups across three tools. Versions qualification against SOP revision. When the work instruction changes, the system flags every operator qualified against the previous version, queues the retraining, and tracks completion against the new revision. The audit answer becomes a query, not an archaeology project. Surfaces gaps before they become incidents. Coverage on cell 4 for night shift is two operators. One transfers. The system shows the gap as a forward-looking risk, not as a problem the production planner discovers Monday morning. Becomes the source the other systems read from. The MES schedules work against verified qualifications. The LMS targets retraining against the people who need it for the next revision. The audit log carries the proof that the operator running the part this morning was current against the controlled revision. None of this requires the floor to do anything different. Operators still run their cells. Supervisors still assign their shifts. Quality still does its audits. What changes is that the data backing all of it is finally accurate, current, and reachable. The Math That Makes the Case The patterns we see in mid-to-large manufacturers point at three quantifiable shifts when work-cell-level competency becomes visible. Audit findings drop. Four of the top five recurring ISO 9001 / 13485 / AS9100 findings live inside the document ↔ training ↔ competency triangle — and almost all of them fail at the "prove the operator was qualified against this specific revision" question. When the answer is a query, the findings stop recurring. Cross-training accelerates. Identifying the second and third operator who could be qualified for a given cell turns from a manager's guess into a gap-analysis output. Single-points-of-failure on the line become visible months before they become problems. Onboarding velocity improves. New hires reach productive qualification two to three weeks faster because the path is mapped: here are the cells you'll be qualified on, here's the learning plan against each, here's the assessment that proves you're there. These aren't moonshots. They're the operational consequences of treating skills as live data instead of as a quarterly artifact. Where it Starts The starting point in any manufacturer's skills program isn't a tool. It's the work-cell map — the inventory of which cells, lines, processes, and quality steps actually exist, and what competency is required to operate each one. Most floors have this map in heads or in PDFs; the manufacturers who win at this make it a queryable structure with proficiency requirements attached. From there, the spreadsheet becomes a live competency matrix — the same view the supervisor was building in Excel, now wired to assessments, certifications, and revisions. The skill data starts feeding the LMS, the MES, the audit reports, and the talent development conversations for operators who want to grow. The shift isn't process change. It's data architecture. And on a floor where uptime and audit-readiness are operational currencies, getting that architecture right is worth more than another training module nobody had time to take. Frequently Asked Questions What's the difference between a training matrix and a competency matrix? A training matrix records what people have been through — courses, modules, sessions. A competency matrix records what people can currently do — assessed against a defined standard, against a specific work cell or process, against the current revision of the work instruction. Training matrices answer did they sit through it. Competency matrices answer can they run it tomorrow. On a regulated floor, the second answer is the one the auditor wants. Why does versioning against SOP revision matter so much? Most quality incidents in regulated manufacturing trace back to an operator running work against an outdated procedure. A competency record that doesn't pin qualification to a specific SOP revision can't prove the operator was current on the actual instructions in force at the time of the work. ISO 9001 clause 7.2 (competence), ISO 13485 clause 6.2, and AS9100 all expect this proof. Without revision-aware competency tracking, the documentation gap is structural — no amount of after-the-fact paperwork closes it. How is this different from what our LMS already does? LMS tracks completion of learning content. Competency tracking at the work-cell level adds proficiency assessment against the actual job, not the content about the job. The LMS continues to deliver the training; the competency layer proves the training landed. The two are complementary — LMS as the content delivery system, competency layer as the verification and operational read. Do we need new processes on the floor to make this work? No. The operators run their cells. The supervisors run their assignments. The quality team runs its audits. What changes is the data layer underneath — what was in spreadsheets becomes a queryable system that other tools can read. The floor process is the same; the visibility around it is what shifts. Where does the work-cell map come from? From the operation, not from the vendor. The map is the inventory of cells, lines, processes, and quality steps that already exists on the floor, plus the competency requirements that govern each one. The platform holds the structure and runs the assessments against it; the manufacturer defines what "qualified to run cell 4" means in their language, their standards, their revisions. Pre-built taxonomies don't survive the first walk-through — every floor is different. --- ## Your HRIS Isn't a Skills Platform. Your LMS Isn't Either. Here's What Actually Is. URL: https://skillsdb.com/blog/hris-lms-not-skills-platforms The HRIS sales team will tell you their suite handles skills. The LMS sales team will tell you their content library handles skills. The talent marketplace will tell you their AI infers skills automatically. Everyone in HR tech sells skills now — because the buyer asked for them, because the analyst report rewarded it, because "skills-first organization" became the line every CHRO put in a board deck this year. Most of it is relabeling. Some of it is real. The buyer's problem is telling them apart before signing a three-year contract. Here's how the categories actually break down, what each one is built for, and what's missing when you try to make any of them carry the skills load on its own. What an HRIS is Built for (and what it isn't) Human Resources Information Systems do two things very well: store the employment record and enforce administrative process. Hire date, manager hierarchy, comp band, benefits enrollment, PTO accrual, the legal stuff. The system of record for that you are an employee — not what you can do as one . When HRIS vendors add "skills" they're adding a column to the employee record. It's a field, not an engine. A field doesn't drive engagement. A field doesn't assess proficiency. A field doesn't tell a manager which of her reports can take the new project that came in this morning. HRIS skills modules score well in procurement spreadsheets because the row is checked. They score poorly in production because the data inside the field is whatever the employee typed three years ago at onboarding, or whatever the manager remembered to update during the annual review. A skills-based organization can't run on a field. It needs an engine. What an LMS is Built for (and what it isn't) Learning Management Systems do one thing very well: deliver content. Course library, assignment workflows, completion tracking, compliance reporting. The system that makes sure people sat through the harassment training and signed the policy attestation. When LMS vendors talk skills, they're tagging content with skill labels. Watch the course on negotiation → the system records "negotiation" as a skill against your record. Completion becomes proficiency. Which it isn't, and the L&D leaders running these systems have known it isn't for fifteen years. The reason is uncomfortable: a course tag is the easiest skill signal to capture, and easy signals are what cheap inferences are made of. The category does a real job. People need to consume content; LMS vendors deliver it. The issue is that consumption isn't competency. Sitting through a Python course doesn't make you a Python engineer any more than watching the cooking channel makes you a chef. A skills-based organization needs to know what people can do , not what they've attended . What a Talent Marketplace is Built for (and what it isn't) Talent marketplaces solve a real internal-mobility problem: people don't know what opportunities exist inside their own company, and the company doesn't know what its own people want. The marketplace closes that loop. Project board on one side, expressed interest on the other, an AI matching layer in the middle. The matching depends entirely on the skills data flowing in. And here's where the category quietly takes a shortcut: most marketplaces infer skills from job titles, past projects, LinkedIn profiles, and self-reported tags. The match is only as good as the inference, and the inference is only as good as the source data — which, in practice, is sparse, stale, and largely unverified. A marketplace built on assessed proficiency works. A marketplace built on inferred skills produces matches that look right in a dashboard and fail in real work. Neither the project owner nor the candidate trusts the system after the third bad match, and the marketplace becomes optional infrastructure. A skills-based organization needs verified data feeding the marketplace. The marketplace itself is a feature of mobility, not the foundation of skills. What Skills Intelligence Actually is Skills intelligence is a different category, not a different feature. The job is: Define what skills and competencies the organization actually cares about, in the organization's own language — not a pre-built taxonomy. Assess proficiency through structured manager-plus-self assessment against role benchmarks, on a configurable scale, stored as evidence. Analyze the gap between current proficiency and required proficiency at the individual, team, function, and org level. Connect that analysis to the downstream systems — learning plans, career pathways, succession decisions, resource staffing, workforce planning, internal mobility — through APIs, so the data flows where decisions get made. That's the loop. None of it is novel; everything in the loop has existed in some form for two decades. What's novel is treating it as the architecture, not as a tab in someone else's product. The HRIS, the LMS, and the marketplace are all real categories that do real work. They just aren't this category. The clearest tell is the question of where the canonical skills data lives. In an HRIS-led architecture, it lives as a field on the employee record. In an LMS-led architecture, it lives as a tag on a course. In a marketplace-led architecture, it lives as an inferred profile. In a skills-intelligence-led architecture, it lives as assessed proficiency in a system designed to hold and operate on it — and the HRIS, LMS, and marketplace all read from that system rather than each defining their own. That last sentence is the architecture argument the next two years of HR tech will be decided on. The Complement, Not the Replacement The temptation in a category critique is to position the new category as a replacement for the old ones. That's not the right frame. The HRIS still owns the employment record. The LMS still owns content delivery. The marketplace still owns the mobility experience. Skills intelligence sits underneath all three, providing the layer that makes each of them smarter. Done right, the HRIS still runs payroll but reads skills from the intelligence layer. The LMS still serves courses but targets them at gaps identified by the intelligence layer. The marketplace still matches projects to people but matches on verified data the intelligence layer produced. When a CHRO asks why do we need another tool , the answer isn't "to replace what you have." It's "because the foundation under what you have is missing, and every workforce decision you're trying to make depends on that foundation being in place." Workforce strategy decisions, talent development programs, succession plans, and career pathways all sit on top of a single question: what can your people actually do. The category that answers that question is the category worth investing in. It isn't the one in the footer of the demo deck. Frequently Asked Questions Is a "skills-based organization" just a buzzword, or a real operating model? It's a real operating model when the canonical skills data is treated as the foundation other workforce decisions read from. Recruiting reads from it (what's already inside the building?). Training reads from it (what gap should this program close?). Succession reads from it (who has the assessed proficiency to step into this role?). Workforce planning reads from it (what capabilities do we have, where are the gaps, where do we close them?). When all four reads happen against the same skills data layer, the organization is operating as skills-based. When each function maintains its own list, the term is marketing. Why isn't competency tracking the same as skills intelligence? Tracking is the record-keeping subset — what skills exist, who's certified, when something expires. It's necessary but not sufficient. Skills intelligence adds the assessment layer (proficiency, not just completion), the analysis layer (gap against benchmark), and the development layer (learning plans connected to verified gaps). Tracking is a feature inside skills intelligence; the reverse isn't true. Can we just build skills intelligence on top of our existing HRIS? Most teams who try this find the HRIS data model isn't structured to hold proficiency, assessment cycles, role benchmarks, or career frameworks as first-class entities. You can store the strings, but you can't operate on them — no assessment workflow, no benchmark comparison, no gap visualization, no API surface that other systems can subscribe to. The HRIS is the right place for employment records. It's the wrong place for skills intelligence. How does skills intelligence work with our LMS? The LMS keeps delivering content. The skills intelligence layer tells the LMS which content matters for which person — based on gap analysis, role requirements, and career pathway position. Learning plans get generated against verified gaps, not against generic skill labels. The LMS becomes a high-precision delivery tool instead of a library people browse and abandon. What's the diagnostic test for whether our current stack is actually skills-intelligence-capable? Three questions. Can we answer "who can do X" across the workforce in under a minute, using assessed data rather than memory? Can we show the gap between current and required proficiency for a specific role, with the assessment evidence behind it? Can another system read our skills data via API in production today, not on a slide? Three yeses means you have a skills intelligence layer. Anything less means you have pieces and are still hoping they add up. --- ## The New SkillsDB is Live: Skills Intelligence That Sees What Your Workforce Can Actually Do URL: https://skillsdb.com/blog/new-skillsdb-is-live Today we're announcing the most significant version of SkillsDB in the company's 18 year history. Not a release. Not a redesign. A rebuild — every line of the product, every part of the data model, every workflow — engineered around a single argument we'll defend on any whiteboard: skills are invisible in most organizations, and when they're invisible, every workforce decision built on top of them gets made on assumption. This is the platform we wished existed when the company started in 2008. It's the platform our enterprise customers have been asking for in different shapes for the last five years. It's the one now finally live. Here's what we built, why we built it, and what changes for you starting today. The Argument We Built Around Most organizations don't know what their people can actually do. That sounds like an exaggeration until you sit in a workforce planning meeting and watch what happens. The HRIS produces a list of job titles. The LMS produces a list of completions. Someone pulls a spreadsheet that hasn't been updated in 14 months. A senior manager says "we have plenty of Python engineers" and a junior manager flinches because she knows three of them have moved off the language entirely. Every workforce initiative — recruiting, training, succession, internal mobility, resource planning, AI transformation — sits on top of what people can do . When that layer is invisible, the initiatives compromise each other. Recruiting can't tell what's already inside the building. Training fires generic content at gaps it can't measure. Succession runs on relationships, not capability. Resource planning leans on resumes that are years out of date. This isn't a training problem. It's not even really an HR problem. It's a visibility problem. And the products in the market — LMS with a skills tab, HRIS with a skills field, content platforms that infer skills from what people watched — were never built to solve it. They were built to do other things and now have a skills label glued on. We rebuilt SkillsDB from scratch because the skills intelligence category needs infrastructure that didn't exist. Not an opinion in a deck. Infrastructure in production. What "Skills Intelligence" Actually Means in the New Platform Three properties define the new system. Each one is a deliberate decision the legacy product couldn't make. A real skills database underneath everything. Not a table. A typed, queryable, versioned data layer where skills, competencies, role benchmarks, and proficiency assessments live as first-class entities with relationships. Definitions don't drift across teams because there's one place they're defined. History doesn't get lost because everything is versioned. Identity is resolved across systems because the platform was built knowing it would have to integrate, not assuming it'd be alone. Assessment-first, not inference-first. Proficiency is measured, not guessed from course completion or scraped from LinkedIn. Manager assessment plus self-assessment plus benchmark data, run on a configurable scale, all stored as evidence — not opinions. When a CHRO walks into a board meeting and says "we have these capabilities and these gaps," she can show the receipts. APIs and extensibility from day one. Everything you can do in the UI, you can do via API. Other systems can read from the skills layer, write to it, subscribe to changes. That's how a skills platform survives — by becoming the source of truth other systems consume, not by trying to be the only place anyone logs in. If you've followed the argument we made last week , this is the resolution. We weren't trying to convince you "platforms" is a meaningful word. We were laying down what the word should mean, and then showing you the work. What Changed in the Product The full rebuild touches every surface. Three changes are worth calling out because they change what's possible for the buyer: The skills database itself. Org-wide, real-time, queryable. Search by skill, role, certification, proficiency band, or any combination. Live skills matrix that updates as assessments come in. No more spreadsheet export-and-stare. Assessments and scorecards. Manager + self-assessment side-by-side, against role benchmarks, rendered as radar charts. Historical view across cycles so growth is visible, not anecdotal. Direct hand-off into learning plans that target the actual gap. Career pathways and internal mobility. Skills-based progression maps with the gap analysis baked in. Employees see what's needed to move; managers see who's ready, ready-soon, or still developing. The career conversation becomes specific instead of vague. This is the surface. Underneath, there's a redesigned permissioning model, a new audit log that's actually immutable, multi-language support, and an API surface our enterprise customers have been waiting on for a year. For the full feature pass, the new use cases pages walks through how the platform handles talent development , workforce planning , succession planning , and career pathways — each one rebuilt against the new data model. What This Means if You're Already a SkillsDB Customer You already have access. The new platform is live across your workspace. No data migration to run, no flip-the-switch project to schedule, no waiting list — the upgrade happened. Your skills frameworks, assessments, scorecards, career paths, and certifications are intact and now operate on the new system. Three things to do this week: Sign in and explore the redesigned product and skills matrix views — they're built for daily use, not quarterly review. Forward this post to one peer in another department who's been frustrated with HR tech. The platform's value compounds when more teams build on it. If you want to schedule a walkthrough of the new capabilities, reply to this — we want every customer to see the new system in context, not just discover it. A separate email is coming Wednesday with the specific feature highlights for your team. What This Means if You're Already Evaluating The buyer landscape just shifted. The vendors who pitched "skills features" on top of an HRIS or LMS still have those features. They just have to compete now against a product whose entire architecture is built around the problem they treat as a side dish. The right next step depends on where you are: If you're early — read some of our blog content to get caught up. If you're evaluating — book a walkthrough . We'll show the platform against your specific workforce questions, not a generic demo. If you've already evaluated us and stalled — the rebuild closed the gap you flagged. Get back on a call. We'll catch you up in a single session. Where the Bar Sits Now Eighteen years with the same dedication tells you what holds and what doesn't. Trends come and go. Skills "platforms" appear every cycle. The ones that survive get built on a foundation, not a feature. The ones that don't, end up as a skills tab in a product that's mostly about something else. We built the new foundation. It's now live. It's already running your assessments, your skills frameworks, your career pathways, and the workforce questions your team will ask this quarter. The next time someone in your category uses the word "platform," ask them to draw the data model on a whiteboard. The answer tells you everything. Frequently Asked Questions What's actually new in the rebuild? Every layer. The data model is rebuilt around skills, competencies, and proficiency as first-class entities. The assessment engine is new. The UI is a ground-up redesign for daily use, not quarterly review. The API surface is comprehensive — every UI action is also an API action. The audit log is immutable. Permissioning is redesigned. The full release covers the talent development , workforce planning , succession planning , and career pathways workflows, plus the skills matrix, assessments, scorecards, certifications, and search experiences. Do existing customers need to migrate? No. The new platform rolled out across all workspaces today. Data, frameworks, assessments, scorecards, career paths, and certifications carried over intact. Your CSM can do a walkthrough of the new capabilities — there's no manual migration project to run. How is skills intelligence different from a skills inventory? A skills inventory is a list — who has what, often self-reported, often stale. Skills intelligence is the live system: assessed proficiency against role benchmarks, gap analysis, career frameworks, learning plans connected to verified gaps, and the ability for other systems to read and write through APIs. Inventory is a snapshot. Intelligence is the operating system. What about integrations with our HRIS or LMS? Provisioning works against Okta, Azure AD, Google Workspace, and any major IdP. SCIM and/or the API supports custom integrations into your HRIS for employee data sync, into your LMS for learning plan hand-off, and into reporting tools for capability dashboards. We're not trying to replace the HRIS or the LMS; we're the skills intelligence layer they read from. Where do I start as a buyer? Book a walkthrough — Bring your specific workforce questions. If you want the underlying methodology first, the Skills Matrix Starter Kit is free and a good place to start. The trust posture (SOC2 Type II, GDPR, sub-processor list, DPA, SLA) lives at trust.skillsdb.com for procurement teams that need to start there. Is this a separate product, or an upgrade? An upgrade. Same SkillsDB, same domain, same sign-ins, same data — rebuilt underneath you. Existing contracts and pricing carry over. New capabilities are included; there's no "new SkillsDB premium" tier hiding the upgrade behind a price increase. --- ## Why Most Skills Platforms Aren't Actually Platforms (and what that means for your workforce strategy) URL: https://skillsdb.com/blog/why-most-skills-platforms-arent-platforms Open the homepage of any vendor selling into HR right now and you'll find the word "platform" everywhere. Skills platform. Talent platform. People platform. Workforce intelligence platform. The word has done so much work in the last three years that it's stopped meaning anything. That's a marketing problem for the category. It's a strategy problem for the buyer. Because if you bought a "platform" expecting one thing and got another, you're a year into rollout before you find out — and by then the spreadsheets are already crawling back into your workforce planning meetings. What an Actual Platform is A platform has three properties that a tool does not. First, it has a data layer that other things can be built on . A skills database isn't a tab in a product — it's the source of truth that recruiting, learning, succession, and workforce planning all read from. If the same skill has different definitions in your LMS, your HRIS, and your performance review software, you don't have a platform. You have three tools with overlapping labels. Second, it has APIs and extensibility . The data is reachable. Other systems can read from it and write to it. New use cases can be built on top of it without filing a feature request and waiting two quarters. The product team using it can extend it; the IT team integrating it can trust it. Third, it has a system-of-record posture, not a system-of-engagement posture . The difference matters. A system of engagement is where the work happens this week — chat tools, project trackers, training pages. A system of record is where the canonical truth lives — financial data, customer data, and yes, skills data. Systems of engagement come and go. Systems of record outlast vendor changes, org redesigns, and acquisitions. They're the floor the rest of the stack sits on. A real skills platform is all three. Most products marketed as skills platforms are none. The "Glorified Spreadsheet with Sign-in" Pattern Strip the marketing and a lot of the category looks like this: a single table where each row is a person, each column is a skill, and each cell is a rating. Add a sign-in screen. Call it a platform. You can do this in Google Sheets. People do. The same pattern shows up in three slightly different costumes: The LMS with a skills tab. Skills as a metadata layer on a content library. The product is courses; skills are how you tag them. Course completion doesn't measure competency, and nobody pretended otherwise until "skills" became the headline a year ago. The HRIS with a skills field. Skills as a column in the employee record. Designed for centralized admin, not for the daily engagement that actually moves skills data. A field doesn't drive development. The talent suite "skills module." A module that reads from the suite's other modules. Looks integrated in the demo. In production, the skills definitions don't match the learning module, and the learning module doesn't match the performance module, and the procurement deck doesn't survive contact with the first cross-functional workforce review. Each version has a real job. LMS vendors deliver content. HRIS vendors manage employment records. Talent suites give finance a tidy line item. None of those jobs is skills intelligence — making skills visible, measurable, and connected to the decisions a CHRO has to defend in a board meeting. When you treat a tool like a platform, you get the architectural cost of a platform without the architectural value of one. What Breaks When Your Platform is a List Three things break, in order. Definitions drift. Without a single source of truth, every team rebuilds their own skill list. The L&D team's "Python" doesn't match the engineering manager's "Python." Procurement's "negotiation" isn't the sales org's "negotiation." Six months in, you can't aggregate, you can't compare, and you can't plan. Assessment becomes optional. A list of skills with no proficiency model is a wishlist. You can't tell who actually has the skill versus who self-reported it three years ago when they joined. The "data" is asserted, not verified — which means the workforce strategy built on it is fiction with confidence intervals. Workforce decisions get outsourced to gut feel. When the system can't answer "who can do this work," the answer comes from a manager's memory. Which is fine at 30 people. At 3,000, it's how succession plans become political and resource staffing becomes a recurring crisis. These aren't tooling problems. They're foundation problems. And no amount of bolt-on AI infers your way out of a missing foundation. What a Real Platform Makes Possible The shift from list to platform changes what the conversation in the workforce planning meeting can be about. Instead of "how many people do we have" , the question becomes "what capabilities do we have, what's the gap to next year's plan, and where do we close it." Instead of "did everyone get trained," the question becomes "who can prove they can do the work — and against which version of the SOP." Instead of "who's available for staffing," the question becomes "who's qualified, available, and developing toward where we need more depth six months from now." You can run all of these conversations from a real skills platform. You cannot run any of them from a spreadsheet with a login. The architectural argument matters because the category is about to bifurcate. The next 24 months will separate the vendors who actually built a platform from the ones who shipped a list and called it one. The buyers who can tell the difference will save themselves a rip-and-replace migration in 2028. The Next Step in this Argument We've been fairly quiet for 18 months because we were rebuilding our entire product as an actual platform — data layer, API-first, extensible, system-of-record posture from day one. AI-first. Not a feature dump. An architecture. We'll show you what that looks like next week. In the meantime, if you're evaluating workforce platforms — ours or any other — the questions worth asking are simple: where does the skills data live, who else can read from it, what happens when the next workforce initiative needs to connect to it, and can the vendor draw the architecture diagram on a whiteboard without it turning into a slide deck. The answers tell you whether you're buying a platform or a list. If you want to see how a real skills database connects to talent development and workforce strategy decisions, the methodology is in the Skills Matrix Starter Kit — the same competency framework + skills matrix structure our enterprise customers build on, free. Frequently Asked Questions What's the difference between a skills database and a skills platform? A skills database is the data layer — the canonical source of truth for what skills exist, who has them, and at what proficiency. A skills platform is the database plus the APIs, the assessment engine, the gap analysis, the career framework integration, and the extensibility that lets other systems read from and write to it. A database without a platform around it is a spreadsheet. A platform without a real database underneath it is a UI shell. Is competency tracking software the same as a skills platform? Competency tracking software is a subset of what a skills platform does. Tracking is the record-keeping piece — what skills exist, who's certified, what's expired. A real platform adds the assessment layer (proficiency, not just completion), the gap analysis layer (against role benchmarks), and the development layer (learning plans connected to verified gaps). Tracking without the rest is a compliance tool. The platform is the operating system. Why does the system-of-record vs system-of-engagement distinction matter? Systems of engagement change every two to three years — new chat tool, new project tracker, new training platform. Systems of record outlast them. If your skills data lives inside a system of engagement, it disappears the next time the vendor pivots or your org switches suites. If it lives inside a system of record, it survives. Skills are a multi-decade investment; the system that holds them should match. How do we tell whether a vendor is selling a platform or a list? Three diagnostic questions. (1) Can another system read from your skills data via API in production today, not on a roadmap slide? (2) Is the skills model assessed against benchmarks, or self-reported in a free-text field? (3) Can the vendor walk you through the data model on a whiteboard — entities, relationships, identity resolution — without reaching for the demo? Two out of three is a list with extensions. Three out of three is a platform. What changed at SkillsDB to make this argument credible? We rebuilt the entire product from scratch over the past 18 months — data layer first, API-first, extensibility-first. The launch is next week. The argument is the same one we've been making to enterprise customers privately for two years; we're now ready to make it in public. --- ## SOC2 Type II, GDPR, and What 'Enterprise-Ready' Should Actually Mean for HR Tech URL: https://skillsdb.com/blog/soc2-gdpr-enterprise-ready We recently landed our SOC2 Type II report and refreshed our GDPR posture. Both live in the Trust Center now, alongside the documents procurement teams actually need: DPA, sub-processor list, SLA details, security questionnaire, audit summary. The boring stuff. The stuff that doesn't make it into a demo. The stuff most vendors hide behind an NDA. We're publishing it openly because the bar for "enterprise-ready" HR tech has slipped. A SOC2 badge in the footer used to mean something. Now it shows up next to fonts and bumper stickers. The badge is the floor — and the category has trained buyers to confuse the floor with the ceiling. What SOC2 Type II and GDPR actually cover SOC2 Type II is an audit, not a certification. An independent firm — ours is Johanson Group — watches the operation and verifies the controls described are being followed in practice. Logical access, encryption, change management, vendor risk, incident response, availability, confidentiality. The Type II report is what real auditors read. The badge is the cover page. GDPR is a posture, not a checkbox. It's enforced by the actions the buyer can ask the vendor to take: process individual data within EU borders, sign a redlinable DPA, delete an employee's record on request, hand over a full export, name every sub-processor that touches workforce data. Both matter. Both are the floor. Where most HR tech buyers get gamed "Enterprise-ready" has become a sticker, not a posture. Buyers see SOC2 in the footer and stop asking. Vendors learn that the badge gets them through procurement, so they stop investing past it. Five questions go unasked, and three years later somebody finds out the hard way during M&A diligence or a regulator inquiry. Here's the shorter procurement checklist worth running — these are the questions our enterprise customers ask us during evaluation, and the questions we test our own vendors against: Data residency. Where does workforce data physically live? Can it be pinned to a region? What does the vendor do when a customer in Frankfurt asks for EU-only processing — flip a settings flag, or rebuild the data pipeline? DPA terms. Is the data processing agreement redlinable, or take-it-or-leave-it? Is there an NDA gate before you even see it? Look for clear sub-processor change notification (30 days minimum), termination assistance with a defined export window, indemnity that doesn't cap at a month of fees. Audit trail. Is the activity log immutable — append-only at the database level? Can you export it as evidence for an internal audit or a regulator? What's logged, and who can suppress events? "Soft delete" is not an audit trail. Sub-processor disclosure. Who else touches your workforce data — analytics, support tools, AI providers, infrastructure platforms? Is the list public? Do they notify before changes? "Trust us, we vet our vendors" isn't a sub-processor list. Off-boarding. What happens to the data when you leave? Can you export it all in a structured format? How long is it retained after termination? Is there a defined deletion timeline with proof of destruction? These aren't moonshots. They're the boring middle of an enterprise procurement review. The vendors that earn long-term trust treat them like the actual product. The ones that don't route them to a contract queue and hope you go away. The pricing position Security should never be a tier upgrade. Audit logs, sub-processor disclosure, SLA, the DPA itself — these are floor-level features for any enterprise workforce platform. The minute a vendor moves any of them above a tier line, they're telling you the floor is negotiable. Our position: bundled in every paid plan. The trust center is public. The DPA is viewable without an NDA. The sub-processor list is current. No upsells to enable the floor. What the bar should look like Eighteen years of selling into HR teams has taught us that "enterprise-ready" is whatever the worst vendor in your shortlist managed to clear. That's a problem for the category, not just for us. So we're going to keep publishing the boring stuff openly — the cover sheet and the audit report, the DPA and the sub-processor list, the off-boarding terms and the response-time SLAs. Trust isn't a badge. It's a posture you can verify line by line — and it's the floor under every workforce strategy decision a CHRO will make this year. If you're evaluating us — or any other workforce platform — start at trust.skillsdb.com . If a vendor doesn't have the equivalent, that's its own answer. Frequently Asked Questions What does SOC2 Type II actually cover? SOC2 Type II is an independent audit of how a vendor's security and operational controls perform over a defined period — typically a full year. It covers logical access, encryption, change management, vendor risk, incident response, availability, and confidentiality. Unlike Type I (a point-in-time snapshot), Type II verifies the controls are followed in practice, not just documented. Our most recent report is on trust.skillsdb.com . How is workforce data residency handled in the EU? Customer-side configurable. SkillsDB supports EU-only processing on request — workforce data, assessment records, audit logs, and backups stay within EU regions. This is a settings change, not an architecture rebuild. GDPR-aligned data subject rights (access, export, deletion) work the same regardless of region. What's in our DPA? Our DPA is signed at the master-agreement level, and aligned with GDPR Articles 28 and 32. It includes 30-day sub-processor change notification, termination assistance with a defined export window, audit cooperation terms, and EU Standard Contractual Clauses where applicable. The current version is live and linked from the trust center — no NDA required. Where can I see the SkillsDB security and compliance posture? trust.skillsdb.com — SOC2 Type II report, DPA, sub-processor list, security questionnaire, response-time SLAs, and historical audit summaries. All public, no gating. --- ## 18 Years of Skills Data: The Three Patterns That Actually Predict Whether HR Tech Earns Trust URL: https://skillsdb.com/blog/trust-patterns-18-years We started building skills software in 2008. Eighteen years of history and the pattern that surprises me most isn't about features — it's about which vendors earn long-term trust, and which ones quietly get cut at the first re-org. The list is short. Most don't make it. Trust in HR tech is misunderstood. Buyers think it's about SOC2 badges, recognizable logos, and a strong showing in the right analyst report. Those things matter — but they describe the floor, not the ceiling. They tell you who's allowed in the room. They don't predict who's still there in three years. What predicts long-term trust is something quieter. It shows up after the demo, in the slow work of a real implementation. After 18 years of watching it play out across manufacturing, government, professional services, and aviation, three patterns stand out. They show up early, and they're almost always right. The product changes the buyer's questions, not just answers them Most HR tech demos do the same thing. Take a question the buyer is already asking. Show it answered faster. Cleaner dashboards, prettier charts, the same question with better-looking output. Trustworthy vendors do something different. Their products change what the buyer can ask in the first place. Before usable workforce data, "who should we put on this project?" was answered with resumes, reputation, and gut feel. A buyer with a real skills source of truth can ask a different question entirely: where are the people with the exact skill mix this project needs, what's their current allocation, and who's two skills away from being qualified? That's not a faster version of the old question. That's a new question, made askable for the first time. The vendors that earn long-term trust are the ones whose customers, a year in, are asking questions they couldn't ask before. The ones that don't are still answering 2018 questions on 2026 hardware. When you're evaluating, the test isn't "does this look good in the demo?" — it's "will my team be asking new questions a year from now?" The vendor treats the unsexy work as the actual product The demo is theatre. Year-one reality is signal. Day one, every vendor looks roughly the same. The product team has rehearsed the demo. The slide deck is tight. The CSM is attentive. The differences show up later, in the boring work nobody pitches. Watch what happens when you ask for a DPA review with redlines. An SSO configuration with a non-standard IdP. A custom field your industry needs that nobody else has asked for. A full data export for a regulator. A sub-processor list, by region. The vendors that earn trust handle these like they're the actual product. Documented processes. Named people. Clear timelines. No friction. Often there's a page for it before you ask — ours lives at trust.skillsdb.com , and I'm quite proud of all that lives there. The vendors that don't treat these as edge cases — to be routed to a contract queue, a custom-engineering quote, or a manager escalation. Trust dies in those routing trees. Eighteen years of watching this play out: how a vendor handles the unsexy stuff in month three is a better trust predictor than any demo in month one. The vendor survives the buyer's first big change This is the slowest pattern, and the most reliable one. Enterprise HR tech has a churn cliff nobody talks about. It happens when something inside the buyer's company changes — a CHRO transition, a re-org, an M&A integration, a platform consolidation. The vendor that was "owned" by the previous champion suddenly doesn't have an internal owner. Two things can happen at that moment. The new CHRO either inherits the vendor as infrastructure they need to keep running, or they inherit it as a line item to evaluate. Same vendor, two different fates. The vendors that earn long-term trust become load-bearing for daily work before the change happens. End users rely on them. Workforce decisions — recruiting, staffing, succession — get made through them. The next CHRO can't switch them off without breaking something operational. They stop being "HR tech projects" and become how the company works. The ones that don't earn that get cut at the first re-org. Not because they were bad. Because they were optional. If your vendor would survive your CHRO transition, you've found one. If you can't predict whether it would, you haven't. What's left when the demo is over Trust in HR tech isn't earned in the demo. It's earned in the slow, unglamorous work the demo doesn't cover. Eighteen years has taught us that the signals are quieter than buyers expect. New questions a year in. No friction on the requests that don't sell. Survival through the buyer's first big change. When all three show up, the vendor stops being a vendor. They become part of how the workforce gets understood — which is what skills intelligence has to be to matter. That's what we're building for. We'd rather earn that than be on a slide. Frequently Asked Questions What predicts whether an HR tech vendor will earn long-term trust beyond SOC2 and customer logos? Three patterns show up consistently over an 18-year window: whether the product changes the questions the buyer can ask (not just answers existing ones faster); whether the vendor treats unsexy procurement work — DPAs, SSO, data exports, sub-processor disclosure — as the actual product; and whether the vendor survives the buyer's first big internal change, like a CHRO transition or re-org. Why do some HR tech vendors get cut after a CHRO transition while others don't? Vendors that were "owned" by a single champion get inherited as line items by the next CHRO. Vendors that became load-bearing for daily workforce decisions get inherited as infrastructure. The difference is usage depth before the transition — whether end users actually rely on the product to do their work. What's a stronger trust signal than a SOC2 Type II report during HR tech evaluation? SOC2 Type II is the floor, not the ceiling. Stronger signals: a public sub-processor list, a redlinable DPA with no NDA gate, SSO and SCIM included rather than tier-locked, documented response times for security questionnaires, and a trust center that exists before the buyer asks for one. Should HR tech security and compliance be a tier upgrade? No. Treating SSO, SCIM, audit logs, and basic security as premium upgrades signals that the vendor sees security as a revenue lever rather than the floor for enterprise use. The vendors that earn long-term trust bundle the security floor into the standard product. How do you tell during evaluation whether an HR tech product will still matter in a year? Ask the vendor for examples of customers a year in. Not the case study with the dashboard screenshot — the boring follow-up: what are those customers doing with the product now that they couldn't do before? If the answer is "running the same reports faster," the product is a tool. If the answer involves workforce decisions that weren't possible before, the product is infrastructure. --- ## 5 Workforce Questions Every Board Will Ask in 2026 URL: https://skillsdb.com/blog/5-workforce-questions-boards-ask-2026 Most board meetings used to have one workforce slide. Total headcount, attrition rate, planned hires. Maybe a slide on DEI or engagement scores. The conversation was about cost. That conversation is changing fast. In 2026, boards are pressing CHROs on capability — what the workforce can actually do, where the strategic risks sit, and whether the talent investment is producing measurable capacity. The questions are getting sharper because the stakes are. AI restructuring roles. Talent costs at all-time highs. Strategic initiatives stalling for skill reasons. Here are the five questions a CHRO should expect this year — and why most organizations can't answer any of them today. 1. "What percentage of our workforce is AI-ready, and where are the gaps?" Why they're asking. Every board has heard some version of "AI is going to transform our business." The question that follows is whether the workforce can actually do the transforming. A roadmap that depends on AI-augmented work is worthless if the people doing the work can't use the tools. Why most orgs can't answer. "AI-ready" isn't a single skill — it's a cluster of capabilities that vary by function. Prompt engineering matters for marketing. Model evaluation matters for analytics. Tool integration matters for engineering. Most HR systems have, at best, an "AI training completed: yes/no" field. That isn't readiness. It's a course completion log. What answering requires. A defined AI competency framework per function, structured assessments against it, and a rollup that shows the actual distribution of capability across the workforce. Without that, the answer is anecdotal. 2. "If we lost 20% of our senior engineers tomorrow, how many internal successors do we have?" Why they're asking. Talent concentration risk has moved from a contingency question to a 2026 planning question. Senior engineers leaving for AI startups, regulated industries facing licensure cliffs, manufacturers with retiring institutional knowledge — all the same shape of risk. Why most orgs can't answer. Succession planning is one of the most uneven practices in HR. Most companies have lists of "high potentials." Far fewer have a documented match between the skills required by each critical role and the verified skill profile of internal candidates. So the board gets a name, not a readiness score. What answering requires. A skill-based view of each critical role — the competencies that define it at a senior level — paired with a verified proficiency profile for every candidate. The question "do we have three ready-now successors for this role" should be a query, not a discussion. Succession planning built on skills data turns that conversation from gut feel into evidence. 3. "What percentage of our open roles could be filled internally?" Why they're asking. Internal hires cost 1.5–3x less than external ones, ramp faster, and stay longer. Boards are asking how much of next year's hiring plan could be redirected — and where the friction is sitting. Why most orgs can't answer. Internal mobility programs exist on most enterprise org charts. Most of them run on self-tagged interests, manager referrals, or AI inference from job titles. None of those are skills data. So when the question becomes "what percentage of our open senior PM roles have a qualified internal candidate," the system can't compute it. What answering requires. A skill profile for every open role and a verified skill profile for every employee, both mapped against the same framework. The match is then arithmetic. Without the data, internal mobility is a marketing message rather than a hiring channel. 4. "How is our training spend tracking against measurable capability growth?" Why they're asking. Training spend across a large enterprise routinely hits the high single-digit millions per year. Boards are no longer satisfied with completion rates and hours delivered — they want to know if capability is actually moving. Why most orgs can't answer. The LMS reports activity. Engagement surveys report sentiment. Neither measures whether the skill being trained actually improved. The transfer rate of training to job application sits around 12% by the most-cited research — which means 88% of spend is producing nothing measurable, but nobody can isolate which 88%. What answering requires. A pre-training proficiency baseline, a post-training reassessment against the same framework, and a delta report by skill, team, and spend bucket. None of those exist as a default workflow in any LMS. They require the layer above — a skills system that measures what the training was supposed to change. Talent development gets defensible to a board the moment training routes from gap data, not from a catalog. 5. "Where are our skill concentration risks — the single points of failure?" Why they're asking. Boards have caught up to the operational reality that some skills live in one or two heads. When those people leave, retire, or get poached, a capability disappears. The question isn't theoretical. It shows up as project delays, customer commitments missed, audit findings. Why most orgs can't answer. Concentration risk requires a workforce-level view of who holds which critical skills, at what proficiency, across what business units. The data lives in spreadsheets, manager memory, and occasionally a tribal-knowledge wiki. There's no rollup. There's no alert when the count drops below safe thresholds. What answering requires. A skills inventory queryable by skill, role, and business unit, with proficiency-weighted counts and thresholds defined for each critical capability. Reviewed quarterly, not annually. This is one of the most basic outputs of a real workforce strategy function — and one of the most consistently missing. The pattern Five questions. Same answer. Each of them routes back to data the organization doesn't have in a queryable form: verified, structured skills data at the individual, role, and workforce level. Without that, the CHRO is bringing anecdotes to a board that wants evidence. With it, the conversation changes — board questions become reports, not discussions. The boards asking these questions aren't being unreasonable. They're catching up to the fact that workforce capability is now a board-level risk, not an HR line item. The CHROs who can answer in 2026 will spend the next year setting an entirely different agenda than the ones who can't. If you want a fast read on where your organization currently sits, the Skill Gaps Calculator scores visibility across four dimensions in about two minutes. It won't answer all five questions on its own — but it'll tell you whether your data is anywhere close to ready. FAQ What does a board want to know about workforce capability? Boards in 2026 are pressing on five questions: AI readiness across the workforce, succession depth for critical roles, internal mobility rate against external hiring, training spend tied to measurable capability growth, and skill concentration risk (single points of failure). All five require verified, queryable skills data — which most HR stacks don't keep in any structured form. How do you measure AI readiness in a workforce? Define an AI competency framework per function (not org-wide), with the specific skills that constitute "ready" for that role family. Assess each employee against the framework with structured manager and self-assessments. Roll up the data by function, geography, and seniority. The output is a percentage and a gap map, not a binary yes/no. What's a skill concentration risk? A skill concentration risk is a critical capability held by too few people. When a regulated process, a customer commitment, or an institutional knowledge area depends on one or two staff members, that's a concentration risk. Boards want to see these explicitly mapped, with thresholds, and reviewed quarterly — not surfaced only when someone resigns. How do CHROs prepare for board-level workforce questions in 2026? Build the data layer that answers these questions before they get asked. That means structured competency frameworks for critical roles, verified assessments of the workforce against those frameworks, and rollups that surface AI readiness, succession depth, internal mobility candidates, training ROI, and concentration risk on a queryable basis. The CHROs who lead on this in 2026 will be setting the workforce agenda for 2027. The board asking these questions is the easy part. Getting in a position to answer them is the work. --- ## The Skills Stack: What Belongs Above Your HRIS URL: https://skillsdb.com/blog/the-skills-stack Open the talent suite from any major HR vendor and somewhere in the menu, you'll find a tab marked "skills." Open the LMS — there's a skills field there too. Open the talent marketplace — skills again, this time as inferred tags. Open the workforce planning tool — skills, this time as headcount categories. Four products. Four different definitions. Four different sources of truth. None of them talking to each other. Most HR tech stacks are running on assumed skills data without a single layer that actually owns it. That isn't a vendor problem. It's an architecture problem — one that becomes obvious the moment you draw the stack honestly. The stack everyone is building, nobody is naming Every enterprise of any size is running roughly the same talent infrastructure. It just hasn't been formalized into a category. Here's the honest layout: Layer What it answers What lives there Mobility Where talent goes Talent marketplaces, internal job boards Development How talent grows LMS, LXP, learning plans Intelligence What talent can do (the missing layer) Records Who works here HRIS, HCM Three of these four layers exist as named, mature categories. The fourth — intelligence — gets approximated by metadata bolted onto whichever product the buyer chose first. That bolt-on is what's failing. Records: who works here The HRIS knows your employees exist. It knows when they were hired, what they're paid, what their title is, who they report to, when they took PTO. This is the system of record for people . It isn't — and was never designed to be — the system of record for what those people can do. A skills field added to a Workday or SAP employee record is a database column, not a skills program. It captures self-reported tags. It doesn't verify proficiency, doesn't map to a competency framework, doesn't generate a gap analysis, doesn't connect to a learning plan. It's a checkbox in a record that wasn't built for capability tracking. The records layer is excellent at what it does. It's a poor place to keep the answer to "what can our workforce actually do." Development: how they grow The LMS and LXP layer answers a different question: given a person and a topic, deliver content. The taxonomy here is courses and consumption . Skills appear as metadata to make content easier to navigate — but the data flows the wrong direction. Skills get inferred from courses taken, not measured directly. Watching a course doesn't mean you can do the thing. This is the well-worn critique of every LMS that bolted "skills" onto its metadata layer in the last three years. The critique is correct — but it's a category error to ask the development layer to fix itself. Development is downstream of intelligence. It can deliver content beautifully, once something else has identified what content is needed. Mobility: where they go The newest layer is the talent marketplace — the internal mobility platforms that match employees to opportunities. The match runs on skills. The skills come from somewhere. In practice, "somewhere" is a combination of self-tagged interests, AI inference from job titles, and resume parsing. The marketplace optimizes for matching, not measurement. Which means a marketplace's recommendations are only as accurate as the skills feed beneath it — and most of that feed is unverified. A talent marketplace running on inferred skills is matching on incomplete data and confidently surfacing the wrong people for the wrong roles. The missing layer: intelligence Sitting between records and development is the layer most enterprises haven't formalized: a structured, verified, decision-ready source of truth for what people can actually do . This is the intelligence layer. Its job is narrow and load-bearing: Define skills and competency frameworks in your organization's language, mapped to your roles. Capture proficiency through structured manager and self-assessments — not inference, not consumption signals. Produce gap analyses against role benchmarks and strategic capability targets. Make the result queryable across teams, geographies, and business units. Expose the data, cleanly, to every other layer in the stack. That last point is what makes it infrastructure rather than a feature. The intelligence layer doesn't replace the LMS — it tells the LMS what to recommend. It doesn't replace the marketplace — it gives the marketplace verified data instead of inferred tags. It doesn't replace the HRIS — it sits next to it, the way a CRM sits next to a finance system. Most enterprises today are trying to run the intelligence layer as a column inside one of the other three layers. That's the equivalent of running customer relationship data inside the accounting system. It looks plausible until you actually need to make a decision with it. Why this layer is purpose-built, not a feature The temptation is always to ask why a skills platform can't just be a module of the HRIS or LMS. The answer is the same reason a CRM isn't a module of QuickBooks: the data model, update cadence, and decision surface are completely different. A skills library needs to be defined in the customer's language, evolve as roles evolve, and produce structured frameworks — not a flat tag list. Gap analysis needs to compare verified proficiency against role benchmarks and strategic targets, not infer from course completion. Workforce-level rollups need to query the data the same way finance queries the general ledger — by team, function, location, time period. These are infrastructure-grade requirements. They don't survive being a checkbox in a record system or a metadata field in a content library. Trying to fit them there is why HRIS-powered skills initiatives and LMS-powered skills programs both quietly stall around month nine. A logical extension Once the intelligence layer is named and built, every other layer gets more accurate. Talent development routes against real gaps instead of catalog availability. Workforce strategy prices against actual capability rather than headcount approximations. Mobility platforms get a clean signal to match on. Succession plans get evidence instead of opinion. The stack only works when every layer does its own job — and the intelligence layer is the one most enterprises haven't yet drawn on the architecture diagram. It belongs on the diagram. It belongs above the HRIS. It belongs as its own category, with its own product, owned by L&D rather than HR Operations. You don't need a different LMS or a different HRIS to run a serious skills program. You need the layer above them. FAQ What is a skills intelligence platform? A skills intelligence platform is the layer in the HR tech stack responsible for defining, capturing, and exposing verified skills data across the organization. It owns competency frameworks, manager and self-assessments, gap analyses, and the workforce-level rollups that downstream systems (LMS, talent marketplace, workforce planning) consume. It sits between the HRIS (records) and the LMS (development) — purpose-built for capability, not records or content delivery. Where does a skills platform fit in the HR tech stack? It sits between records (HRIS) and development (LMS/LXP). The HRIS owns who works here. The LMS owns how content gets delivered. The skills intelligence layer owns what people can actually do — and feeds that signal upstream to mobility, succession, and workforce planning, then downstream to development so training is sourced against real gaps. Is a skills platform a replacement for an LMS? No. The LMS delivers content. The skills platform tells the LMS what content to deliver, to whom, and why. They serve different layers of the stack. Most enterprises end up running both — the skills platform identifies the gap, the LMS closes it. What's the difference between an HRIS skills module and a skills platform? An HRIS skills module is a column on a record — a place to store self-reported tags next to other employee data. A skills platform is a system of record for capability: structured competency frameworks, verified assessments, gap analysis against role benchmarks, and a decision surface that other systems consume. The HRIS skills column is for compliance and lightweight tagging. The skills platform is for workforce decisions. If your HR tech stack is built without the intelligence layer, every other layer is running on assumed data. The fix isn't a better LMS or a smarter HRIS — it's drawing the layer that should have been there from the start. --- ## What Skills Invisibility Actually Costs You URL: https://skillsdb.com/blog/cost-of-invisible-skills Most workforce budgets are negotiated in two columns: headcount and training spend. They are scrutinized line by line. Approved with caveats. Adjusted at the margins. Then the year ends, and nobody can actually say what either column produced. That isn't a budgeting failure — it's a visibility failure. And it has a price tag. Skills invisibility gets treated as a soft problem. A culture problem. An HR problem. It isn't. It's a financial problem with three quantifiable line items hiding inside it, and any CFO who looks for them will find them. The CFO question that has no answer A board asks the CHRO: "How much of our $4M in training spend last year actually moved the work?" The honest answer is "we don't know." But that answer doesn't survive a board meeting, so what gets reported instead is completion rates. Hours delivered. NPS scores from the LMS. These metrics describe activity. They don't describe outcomes. And the gap between the two — between training delivered and capability gained — is where the real cost lives. The $3M you can't staff For services firms, the most expensive invisibility sits on the bench. You win a deal. Kickoff is in three weeks. Sales hands the engagement to delivery, and the resource planner opens the staffing spreadsheet — last updated by hand, three months ago, by someone who has since left. The right people for this engagement may already be on staff. Three of them. Two are between projects. One is misclassified on a different practice line. The planner doesn't see this, because the data needed to see it doesn't exist in any structured form. So the firm hires externally at 1.5–3x the loaded cost of an internal redeploy, or the engagement starts with the wrong staffing and the margin gets eaten in week four. The same pattern surfaces as the same number across services firms running their first real skills inventory: roughly $3M in capacity that was already on the payroll, just invisible. Same headcount, same spend, three additional staffable projects per year once the skills became visible. That isn't a productivity improvement. It's a depreciation reversal. Resource planning without skills data is just headcount math. The mobility leakage you can't see The second invisible cost shows up at exit interviews and never makes it into the workforce model. LinkedIn's 2024 Workplace Learning Report puts the numbers cleanly: 76% of employees say development opportunities are important to whether they stay. 36% say what their employer offers is actually relevant. That 40-point gap isn't a perception problem. It's the felt experience of an employee who can't see what skills get them to the next role, can't tell if the training catalog applies to their path, and concludes — correctly — that growth at this company is something that happens to other people. So they leave. The replacement costs 1.5–3x their salary. The institutional knowledge walks out the door. The career path they couldn't see remains invisible to the person who fills their seat. Most CHROs would say their company has career paths. Most employees would say they can't find them. Both are right. The paths exist as documents. They don't exist as visible, skill-defined progressions employees can score themselves against and act on. When career progression is invisible, retention is a coin flip you keep losing. The training spend that doesn't translate The third and largest line item is training itself. Corporate training spend per employee runs around $1,800 per year on average. Multiplied across a 5,000-person enterprise, that's $9M annually — and Harvard Business Review's well-cited Beer et al. research puts the actual transfer rate (skills applied back on the job) at 12% . Twelve percent. This isn't a training-quality problem. It's a relevance problem. Training that gets sourced before assessing the skill gap it's meant to close cannot, by definition, close it reliably. Sometimes the catalog matches the need by accident. Often it doesn't. The other 88% of spend produces certificates, completion stats, and very little capability. You don't fix this with better courses. You fix it by assessing the gap first, then sourcing training against the gap — which requires knowing what the gap actually is, at the individual and role level, with verified data. This is what skills-based talent development means when it's taken seriously: training routes from real gap data, not from a catalog of available content. Visibility as infrastructure Stack the three costs and the magnitude is uncomfortable. For a 5,000-person services enterprise: roughly $3M in unrecovered bench capacity, multiples of that in regrettable attrition driven by career invisibility, and 88% of a $9M training budget producing no measurable capability lift. None of these numbers show up as line items in a financial model — because the data needed to surface them isn't kept anywhere it can be queried. This is the point worth sitting with. Skills visibility isn't a feature you add to a workforce strategy. It's the substrate every other workforce investment runs on. Without it, training spend, hiring decisions, succession plans, resource allocations, and retention investments are all priced on assumption rather than evidence. A workforce decision made on invisible data is a workforce decision priced wrong. The job of a skills platform is to make that substrate visible — to translate "what skills do we have, where are the gaps, where is the concentration risk?" from a question nobody can answer into a query anyone can run. Once that exists, every downstream investment becomes defensible to a CFO. Not because the spend changes, but because the spend can finally be evaluated against capability outcomes. Visibility isn't a feature. It's the layer that makes every other workforce investment defensible. If you want a sense of where your organization sits today, the Skill Gaps Calculator takes about two minutes and scores your visibility across four dimensions. The result isn't a sales artifact — it's a number you can put in front of finance and ask better questions about. FAQ How much do invisible skills cost a company? The cost compounds across three buckets: misallocated headcount (services firms typically uncover $2–3M in unrecognized bench capacity per 500 employees once skills become visible), regrettable attrition driven by invisible career progression (LinkedIn reports a 40-point gap between employees who say development matters and those who say their company's offering is relevant), and training spend that doesn't transfer (only 12% of skills learned in training are applied back on the job, per Beer et al. in HBR). What's the ROI of skills visibility? The ROI shows up downstream. Once skills are visible, training can be sourced against actual gaps (lifting application rates well above the 12% baseline), bench can be staffed from internal capability instead of external hires (1.5–3x cost difference per role), and career conversations can be grounded in skill-defined progression instead of generic ladders. The visibility itself doesn't generate revenue — it re-prices every existing workforce investment against capability outcomes. How do you quantify hidden bench capacity? Build a skills inventory at the individual level, mapped to the same role framework you use to scope projects. Compare available staff with the skill profile against open or upcoming project demand. The hidden capacity is the count of staffable engagements you couldn't see before — typically several per quarter for a services firm running its first inventory. Why does training spend underperform without skills data? Because the training catalog is sourced independently of the gap it's meant to close. Course recommendations come from the catalog, not from the data. When the match between training and gap happens, it's incidental. Skills-first inverts that: assess the gap, then source training against it. Same spend, dramatically different applied rates. If you're building the case to your CFO for a different workforce model in 2026, workforce strategy that runs on skills data is where to start. --- ## How to Run Competency Assessments That Produce Data You Can Trust URL: https://skillsdb.com/blog/competency-assessment-guide The assessment is where competency frameworks meet reality. It's the moment you stop talking about what skills people should have and start measuring what they actually do have. And it's the step most organizations either skip or execute so poorly that the data is useless. A competency assessment measures an individual's demonstrated capability in specific skills against a defined proficiency scale. Not their potential. Not their training history. What they can do right now, at what level, validated through structured evaluation. When done well, assessments produce the most valuable data in your entire HR stack. When done poorly, they produce noise that erodes trust and wastes everyone's time. Why Most Assessments Fail Self-assessment alone is unreliable People are bad at rating their own skills. Dunning-Kruger is real — the least competent tend to overrate themselves, and the most competent tend to underrate. A study published in the Journal of Personality and Social Psychology found that self-assessments correlated poorly with objective performance measures, with the bottom quartile overestimating their ability by an average of 50%. Annual cadence is too slow Running assessments once a year means working with stale data for 11 months. Skills develop. Roles change. People join and leave. By the time you act on annual assessment data, it's describing a workforce that no longer exists. Disconnected from everything The assessment happens. Data gets collected. Then nothing changes. It doesn't feed into development plans, career conversations, or workforce decisions. When people see that assessments don't lead to action, they stop taking them seriously — and data quality collapses. The Dual Assessment Model The most reliable method: combine self-assessment with manager assessment. Both parties rate the employee against the same competency framework , using the same proficiency scale . Why both? Self-assessment captures skills managers don't directly observe — technical depth, problem-solving approaches, collaboration with other teams Manager assessment provides an external calibration check — correcting for blind spots and overconfidence The gap between self and manager ratings is itself valuable data — large discrepancies indicate either a calibration problem or a visibility issue How it works in practice: Employee rates themselves on 8-12 competencies using the 5-level proficiency scale Manager independently rates the same employee on the same competencies System highlights discrepancies (where ratings differ by 2+ levels) Manager and employee discuss discrepancies in a brief calibration conversation Final ratings are recorded and feed into gap analysis The entire process takes 15 minutes per person for self-assessment, and 10-15 minutes per direct report for managers. For a team of 8, that's about 2 hours of total manager time per quarter — a fraction of what most organizations spend on annual reviews that produce less useful data. Running the Assessment: Step by Step Step 1: Prepare the framework Before anyone rates anything, ensure the competency framework is clear: Each competency has a definition that everyone interprets the same way Each proficiency level has behavioral indicators specific to the role family Managers have been calibrated on what each level looks like Step 2: Communicate the purpose Assessments fail when people think they're being judged rather than developed. Frame the assessment as a development tool: "This measures where you are so we can build a targeted development plan" "There's no pass or fail — every rating is a data point for growth" "Your self-assessment matters as much as your manager's" Step 3: Run dual assessments Give both parties a defined window (1-2 weeks). Don't let it drag — urgency produces higher quality responses. Late assessments tend to be hasty. Step 4: Review discrepancies Flag any competency where self and manager ratings differ by 2 or more levels. These need a conversation. Sometimes the employee undervalues a skill. Sometimes the manager isn't seeing work that happens outside their view. Either way, the conversation is valuable. Step 5: Generate gap data With assessment data in, gap analysis becomes automatic: for each person, calculate the distance between their assessed proficiency and their role's requirements. Aggregate by team. Aggregate by organization. The gaps tell you where to invest. Step 6: Connect to development Every significant gap should map to a learning plan within two weeks of assessment completion. Assessments that don't lead to action lose credibility fast. When employees see that their assessment data directly informs their development opportunities, engagement with future assessments improves. Assessment Frequency Quarterly is the sweet spot for most organizations. It's frequent enough to track real skill development, infrequent enough to avoid assessment fatigue. Monthly makes sense for fast-moving teams (early-stage startups, rapid-growth departments) or for new hires in their first 6 months. Annual is too slow. By the time you act on the data, it's describing a different workforce. Reserve annual cadence only as a fallback if quarterly isn't organizationally feasible. Measuring Assessment Quality Track these signals to know if your assessments are producing trustworthy data: Completion rate: Target 90%+. Below 80% means the process is too burdensome or people don't see the value. Self-manager correlation: Some gap is expected and healthy. Massive systematic divergence (everyone rates themselves 2 levels higher than their manager) means the scale isn't calibrated. Score movement: If scores never change quarter to quarter, either development isn't happening or people are auto-filling their previous answers. Both are problems. Action rate: What percentage of identified gaps result in a development action within 30 days? If it's below 50%, the assessment-to-action loop is broken. FAQ What is a competency assessment? A competency assessment measures an individual's demonstrated proficiency in specific skills against a defined scale. It captures what someone can actually do today — not their training history or potential — using structured evaluation methods like dual self-and-manager assessment. What is the best method for assessing employee competencies? Dual assessment (self + manager) produces the most reliable data. Self-assessment captures skills managers don't directly observe. Manager assessment provides external calibration. The gap between the two is itself valuable diagnostic data. How often should competency assessments be conducted? Quarterly is optimal — frequent enough to track development, infrequent enough to avoid fatigue. Each assessment takes about 15 minutes for self-assessment and 10-15 minutes per direct report for managers. How do you ensure competency assessments are fair and consistent? Three practices: use behavioral indicators (specific, observable descriptions of each proficiency level), calibrate managers before assessments (ensure consistent interpretation of the scale), and use dual assessment to reduce individual bias. What do you do with competency assessment data? Connect it to gap analysis (identify where people fall short of role requirements), learning plans (target development at specific gaps), career pathing (show progress toward next-role readiness), and workforce planning (aggregate team and org-level capability data). --- ## Skills Tracking vs. Skills Intelligence: What's the Difference? URL: https://skillsdb.com/blog/skills-tracking-vs-skills-intelligence Most organizations that say they "manage skills" are really just tracking them. They have a spreadsheet, an HRIS field, or maybe a dedicated tool that records what skills employees have. That data sits somewhere. Occasionally someone looks at it. And workforce decisions continue to be made on gut feel, manager opinion, and whoever spoke up loudest in the staffing meeting. Tracking skills and using skills intelligently are two fundamentally different things. The distinction matters because the HR technology market is full of vendors that sell "skills management" when what they deliver is a database. The gap between recording data and operationalizing it is where most organizations lose the value of their investment. What Is Skills Tracking? Skills tracking is the process of recording and maintaining data about employee skills, competencies, and certifications. It answers a basic question: what skills does this person have? A skills tracking system stores skill names, proficiency levels, certification dates, and sometimes assessment scores. It is the record-keeping layer of skills management — capturing what exists in your workforce at a point in time. Skills tracking is necessary but insufficient. It gives you a snapshot without context: no gap analysis against role requirements, no connection to training investments, no strategic workforce view. Think of it as a skills census — useful for knowing what you have, but silent on what you need and what to do about it. At its simplest, skills tracking looks like a spreadsheet with names on one axis and skills on the other. At its most sophisticated, it's a searchable database with proficiency ratings and certification expiry alerts. But the defining characteristic stays the same: it records. It doesn't analyze. It doesn't recommend. It doesn't drive decisions. What Is Skills Intelligence? Skills intelligence is the practice of using skills data to analyze workforce gaps, inform development investments, and drive strategic talent decisions. It goes beyond recording what skills exist to answering what skills are missing, where gaps concentrate, which teams are most at risk, and what actions will close the gaps fastest. Skills intelligence connects skill data to business outcomes — staffing decisions, training ROI, succession readiness, and workforce planning. Where skills tracking asks "what do we have?", skills intelligence asks "what do we need, where are the gaps, and what should we do about it?" Skills intelligence requires three things tracking alone doesn't provide: a competency framework that defines what "good" looks like for every role, systematic assessment that measures people against that framework, and analytics that surface patterns and priorities from the resulting data. The Comparison The difference isn't subtle. It's structural. Data model Tracking: A flat list of skills and ratings. Employee X has Skill Y at Level 3. The data exists in isolation — disconnected from role requirements, team needs, or business strategy. Intelligence: A relational model where skills connect to roles, roles connect to competency frameworks, assessments connect to benchmarks, and gaps connect to development plans. The data has context. Time orientation Tracking: Backward-looking. It tells you what skills people demonstrated at the time of their last assessment or profile update. In many organizations, that data is 12-18 months stale. Intelligence: Forward-looking. It identifies emerging gaps based on role requirements, strategic priorities, and workforce trends. It answers: given our strategy for the next 12 months, which capabilities are we short on? Purpose Tracking: Compliance and record-keeping. "Can this employee operate this equipment?" "Does this nurse have a current BLS certification?" These are valid, important questions — but they're operational, not strategic. Intelligence: Strategic decision-making. "Which teams have the deepest skill gaps relative to next quarter's projects?" "What's our bench strength for the three roles most critical to growth?" "Where should we invest our training budget for maximum impact on capability gaps?" Frequency Tracking: Periodic. Updated during annual reviews, onboarding, or compliance cycles. The data degrades between updates. Intelligence: Continuous. Skills data stays current through regular assessment cycles, event-triggered updates (certifications earned, projects completed), and manager input. Deloitte's 2023 Global Human Capital Trends report found that skills requirements for the average job change by 25% every three years — periodic tracking can't keep pace. Output Tracking: Reports and exports. A spreadsheet showing who has what. Useful for audits and headcount planning. Not useful for strategic investment decisions. Intelligence: Insights and recommendations. Gap analysis dashboards that rank teams by exposure. Skills matrices that reveal concentration risk. Learning plans generated from measured gaps rather than catalog browsing. Manager analytics that surface patterns a spreadsheet would never reveal. Who benefits Tracking: HR administrators and compliance teams. The people who need to answer "do we have this certification covered?" and "who's due for recertification?" Intelligence: L&D leaders, CHROs, and business executives. The people who need to answer "are we building the right capabilities?" and "can we execute our strategy with the workforce we have?" What Skills Tracking Looks Like in Practice A mid-size manufacturing company tracks skills using a spreadsheet maintained by the HR team. Each employee has a row. Each required skill has a column. Proficiency ratings are filled in during annual reviews. The spreadsheet is 18 months old. Three employees have left and haven't been removed. Two others completed certifications that aren't reflected. When the plant manager needs someone with Six Sigma Black Belt certification for a new quality initiative, they email HR, who emails the department heads, who check their own records. The answer arrives in three days. Sometimes it's wrong. This isn't failure. The spreadsheet is doing exactly what it was designed to do. But it's tracking — not intelligence. What Skills Intelligence Looks Like in Practice The same manufacturing company, but with a different approach. Competency frameworks define the skills needed for each job family. Assessments run quarterly — both manager and self-assessment — against those frameworks. The data feeds a live system of record. When the plant manager needs a Six Sigma Black Belt, they search the system and get results in seconds. When the VP of Operations asks which production teams have the deepest skill gaps heading into a new product launch, there's a dashboard for that. When the CHRO presents the board with workforce readiness for the company's three-year strategic plan, the data exists and it's current. The training budget connects to measured gaps. Learning plans are generated from assessment data. The L&D team can prove that last quarter's training investment closed 40% of the targeted gaps — because they measured before and after. This is intelligence. Same organization, same skills, fundamentally different capability. Why the Market Confuses the Two The HR technology market uses "skills management" as a catch-all. LMS vendors add a skills taxonomy and call it skills management. HRIS platforms add a skills field to employee profiles and check the box. The proliferation of "skills-based organization" messaging has made every vendor claim they enable skills-driven decisions. The tell is in the architecture. If the platform starts with content (courses, learning paths) and maps skills backward from completions, it's tracking dressed up as intelligence. The skills layer is metadata on a content library — not an independent system that drives decisions. If the platform starts with a skills taxonomy bolted onto an HRIS, it's a data field — not an analytical engine. Recording that someone has "Project Management: Level 3" in their profile doesn't tell you whether that's above or below the benchmark for their role, how it compares to their team, or what development would move them to Level 4. Purpose-built skills intelligence platforms start with the framework — defining what skills each role needs and at what level. Then they assess against that framework. Then they analyze the gaps. Then they connect the gaps to action. The flow is: define, assess, analyze, act. Not: store, report, hope someone uses it. Where Does Your Organization Fall? Most organizations are somewhere in the middle. They track some skills in some format. They have a general sense of where gaps exist. But they can't answer specific questions — which teams, which skills, how deep, at what cost — without a research project. The Skill Gap Calculator scores your organization across four dimensions: Skills Inventory, Gap Visibility, Development Alignment, and Decision Readiness. It takes two minutes and tells you whether your current approach is tracking, intelligence, or something in between. The score matters less than the dimension breakdown. An organization might have a strong skills inventory (they track diligently) but score zero on decision readiness (leadership never sees the data). That's the tracking-to-intelligence gap in sharp relief. Making the Shift Moving from tracking to intelligence isn't about buying new software — although the right platform makes it dramatically easier. It's about changing what you do with skills data. Step 1: Define what "good" looks like. Build competency frameworks that specify the skills each role needs and the proficiency levels expected. Without this benchmark, assessment data has no context. Step 2: Assess systematically. Annual reviews aren't enough. Quarterly dual assessments — manager and self-assessment — produce the most accurate and actionable data. A 2024 study in the Journal of Applied Psychology found that multi-rater assessments produce 31% more accurate competency profiles than single-source evaluations. Step 3: Connect gaps to investments. Every identified gap should link to a development action — training, mentoring, stretch assignment, or hire. If your gap analysis doesn't flow directly into learning plans , you're still just tracking with extra steps. Step 4: Surface insights for decision-makers. Skills data that lives in an L&D team's dashboard but never reaches the CHRO or the business unit leaders is tracking at scale. Intelligence means the data reaches the people who allocate budget, approve headcount, and design organizational strategy. The Bottom Line Skills tracking is table stakes. Every organization does some version of it, even if it's informal. Skills intelligence is the differentiator — the capability that turns workforce data into workforce strategy. The question isn't whether you track skills. It's whether your skills data makes your organization smarter. Whether it reaches the right people, in the right format, at the right time to improve decisions that matter. If the answer is no — or "sort of" — the gap isn't in your workforce's skills. It's in your visibility. And that's the gap worth closing first. Check out the Skill Gap Calculator to see where you stand. FAQ What is the difference between skills tracking and skills intelligence? Skills tracking records what skills employees have — proficiency levels, certifications, assessment scores. Skills intelligence uses that data to analyze gaps, inform training investments, and drive strategic workforce decisions. Tracking tells you what exists. Intelligence tells you what's missing, where the risks are, and what to do about it. Can I have skills intelligence without a dedicated platform? In theory, yes — a disciplined team could build frameworks, run assessments, and analyze gaps using spreadsheets and manual processes. In practice, the manual overhead becomes unsustainable beyond 50-100 employees. The analysis layer — gap identification, trend detection, development alignment — is where dedicated platforms provide capabilities spreadsheets can't replicate. How do I know if my current tool is tracking or intelligence? Ask three questions. Can it show you which teams have the biggest skill gaps right now? Can it trace your training spend to specific measured gaps? Can leadership access workforce capability insights without requesting a custom report? If the answer to any of these is no, you're closer to tracking than intelligence. Is skills tracking still valuable? Absolutely. Tracking is the foundation. You can't analyze gaps you haven't measured. The issue arises when organizations stop at tracking and assume the job is done. Tracking without analysis, connection to development, and decision-making access leaves most of the value on the table. What does a skills intelligence platform actually do differently? A skills intelligence platform starts with competency frameworks, runs systematic assessments against those frameworks, identifies and quantifies gaps at every level (individual, team, organization), connects gaps to development plans, and surfaces insights for decision-makers. The data flows from definition through assessment to action — rather than sitting in a database waiting to be queried. How long does it take to move from tracking to intelligence? For most organizations, the transition takes 3-6 months. Month one focuses on building competency frameworks. Month two introduces systematic assessments. Months three through six build the analysis and decision-making layers. The key accelerator is starting with a focused pilot — one department or job family — rather than attempting an org-wide rollout. --- ## Skills Gap Analysis: The Complete Guide to Finding and Closing What's Missing URL: https://skillsdb.com/blog/skills-gap-analysis-complete-guide Every workforce has gaps. The question isn't whether they exist — it's whether you can see them clearly enough to act before they become costly. A skills gap analysis is the practice of measuring the distance between what your workforce can do today and what it needs to do tomorrow. Not guessing. Not surveying managers for their impressions. Measuring — with structured data, against defined benchmarks, at the individual and team level. Most organizations skip this step entirely. They invest in training based on vendor recommendations, employee requests, or the latest industry trend. They hire based on job descriptions that haven't been updated in three years. They plan workforce strategy using headcount data when they need capability data. The result: training budgets that don't move the needle, hiring that doesn't close the right gaps, and strategic plans built on assumptions instead of evidence. What Is a Skills Gap Analysis? A skills gap analysis compares an individual's, team's, or organization's current skill proficiency against the levels required for their roles, strategic objectives, or future needs. It quantifies the specific distance between where people are and where they need to be — turning a vague sense of "we need to upskill" into a ranked, measurable list of priorities. The analysis requires two inputs: a clear definition of required skills and proficiency levels (a competency framework ), and an accurate assessment of current capabilities ( proficiency assessment ). The gap is the delta between the two. The Three Levels of Gap Analysis Individual gaps Where does this person stand against the requirements of their role? Where are they strong, and what specific skills need development to hit the next level? Individual gap analysis powers development conversations. Instead of a manager saying "you need to work on leadership," the data shows: "You're at Level 2 in stakeholder management. Your role requires Level 3. Here's what Level 3 looks like." Team gaps Where are the collective weaknesses on this team? What skills have single points of failure — only one person rated proficient? Where does the team lack depth? Team-level analysis is where staffing and training decisions live. If the entire team is below proficiency in a critical skill, that's a hiring signal, a training initiative, or both. Organizational gaps Across the company, where are the biggest capability deficits relative to strategic priorities? Which departments are most at risk? Organizational gap analysis feeds workforce strategy . It tells leadership: here's what we need to execute next year's strategy, here's what we have, and here's the distance between the two. How to Run a Skills Gap Analysis Step 1: Define what "good" looks like You can't measure a gap without a target. For each role or role family, define the skills required and the expected proficiency level for each. If you have a competency framework , this is already done. If you don't, start with one team: identify 8-12 critical skills and set expected proficiency levels for each role. This is a 2-3 week exercise, not a 6-month project. Step 2: Assess current state Run proficiency assessments against the defined competencies. Use dual assessment — self and manager — for the most reliable data. Self-assessment alone tends to skew high. Manager assessment alone misses skills managers don't observe directly. The combination produces a calibrated picture. Step 3: Calculate the gaps For each person and each skill: gap = required proficiency − current proficiency. A positive number is a gap. A negative number is a strength. Aggregate by team to see collective gaps. Aggregate by organization to see strategic capability risk. Step 4: Prioritize Not all gaps are equal. Prioritize based on: Business impact: A gap in a skill critical to next quarter's initiative matters more than a gap in a nice-to-have skill Gap size: A 3-level gap requires more intervention than a 1-level gap Breadth: A gap shared by the entire team is more urgent than one person's development need Closability: Some gaps can be closed through training in 3 months. Others require hiring. Know the difference. Step 5: Act Gap analysis without action is just measurement theater. Each identified gap should map to one of three responses: Build: Close the gap through development — learning plans , coaching, stretch assignments, certifications Buy: Hire for the capability externally Borrow: Bring in contractors, consultants, or cross-functional resources for immediate needs while building internally Skills Gap Analysis for Training ROI Here's where gap analysis pays for itself: it turns training from a cost center into a measurable investment. Without gap data, the training budget gets allocated by gut feel, manager requests, or vendor-driven content catalogs. With gap data, every dollar traces back to a specific, measured skill deficit. Before gap analysis: "We spent $200K on training this year." After gap analysis: "We invested $200K to close 47 critical skill gaps across 3 teams. Thirty-one gaps are now within proficiency. Sixteen remain and are targeted in Q3." That's the difference between a budget line and a business case. Common Mistakes Running the analysis once. A gap analysis is a snapshot. Skills change, people develop, roles evolve, strategy shifts. Run it quarterly or it decays into irrelevance. Analyzing without acting. The analysis should generate a prioritized action plan within two weeks. If it sits in a slide deck for a month, you've wasted the effort. Using generic benchmarks. Your competency requirements should reflect your organization, not an industry average. A Level 3 in "data analysis" means different things at a bank, a startup, and a hospital. Ignoring the bright spots. Gap analysis tends to focus on what's missing. Don't overlook the strengths it reveals — people with capabilities the organization isn't leveraging. A resume search across skills data can surface internal experts you didn't know you had. From Analysis to Intelligence A single gap analysis answers: where are we today? Repeated gap analysis over time answers: are we getting better? Which investments are working? Where are new gaps emerging? That's the shift from analysis to intelligence. It's the difference between a report and a strategy. And it's what happens when gap analysis runs on live data in a system like SkillsDB rather than as a periodic, manual exercise. FAQ What is a skills gap analysis? A skills gap analysis measures the difference between the skills your workforce currently has and the skills required for their roles or your strategic objectives. It produces a ranked list of capability gaps at the individual, team, and organizational level, enabling targeted investment in training, hiring, and development. How do you conduct a skills gap analysis? Define required skills and proficiency levels for each role (using a competency framework). Assess current employee proficiency through dual self and manager assessments. Calculate the delta between required and current levels. Prioritize gaps by business impact, size, and closability. Map each gap to a build, buy, or borrow response. How often should you run a skills gap analysis? Quarterly is ideal. Annual analysis decays too quickly as people develop, roles change, and strategy shifts. Quarterly cadence keeps the data fresh enough to drive real-time training and staffing decisions. What is the difference between a skills gap analysis and a training needs analysis? A skills gap analysis measures capability deficits against role requirements. A training needs analysis determines what learning interventions will close those gaps. Gap analysis tells you what's missing. Training needs analysis tells you how to fix it. Gap analysis should feed training needs analysis, not the other way around. Can skills gap analysis be automated? Yes. When competency frameworks and proficiency assessments live in a platform, gap calculations are automatic and always current. Manual gap analysis (spreadsheets) works for one-time exercises but doesn't scale or stay fresh. --- ## Training Needs Analysis: How Skills Data Makes It Easier URL: https://skillsdb.com/blog/training-needs-analysis-skills-data The training needs analysis is one of the most important exercises in L&D — and one of the most dreaded. Every year, someone gathers survey responses from managers, reviews performance data, scans industry trends, and assembles a report that says, more or less, the same thing: we need more leadership development, our technical skills are falling behind, and we should invest in communication training. The report gets filed. Budget gets allocated. Courses get purchased. Six months later, the same gaps exist — because the analysis was based on opinions, not measurement. A training needs analysis (TNA) is supposed to be the bridge between organizational strategy and learning investment. Instead, it's become a bureaucratic exercise that confirms what people already believe and changes nothing. The fix isn't better surveys or more stakeholder interviews. It's skills data. What Is a Training Needs Analysis? A training needs analysis is a systematic process for identifying the gap between an organization's current workforce capabilities and the capabilities required to achieve its strategic objectives. It answers three questions: what skills does the organization need, what skills does it currently have, and what development will close the gap. A thorough TNA examines needs at three levels — organizational (strategy-driven priorities), role-based (job-specific competency requirements), and individual (personal skill gaps against role benchmarks). The output is a prioritized list of learning interventions, mapped to specific gaps, with clear success metrics. When done well, a TNA ensures that training investments target the right people, with the right content, at the right time. Why Traditional TNA Fails The process most organizations follow for training needs analysis was designed for a workforce that changed slowly. Annual TNA cycles made sense when skill requirements shifted over years, not quarters. That world is gone. The survey trap Most TNAs start with surveys: "What training does your team need?" This question sounds reasonable. In practice, it produces a wish list, not a gap analysis. Managers request training they've heard about, training their peers are doing, or training for the loudest skill deficiency on their team. They rarely request training for gaps they haven't noticed — which are often the most critical ones. A 2024 McKinsey survey on workforce transformation found that 43% of organizations rely primarily on manager surveys for training prioritization. The same study found that these organizations were 2.3 times more likely to report misalignment between training investments and business outcomes. The annual cycle problem Running a TNA once a year means you're making 12 months of training decisions based on a single snapshot. By month six, new priorities have emerged, team compositions have changed, and the original analysis is describing a workforce that no longer exists. Deloitte's 2023 Global Human Capital Trends report found that skills requirements for the average job change by 25% every three years. An annual TNA can't detect quarterly shifts in what the organization needs. The aggregation problem Traditional TNAs aggregate upward. Individual feedback becomes team summaries. Team summaries become department reports. Department reports become an organizational analysis. At each layer, specificity is lost. By the time the CHRO sees the final report, "the engineering team needs cloud skills" could mean 5 people need basic AWS training or 50 people need advanced Kubernetes certification. The training investment required differs by an order of magnitude. No baseline, no measurement The most damaging flaw: most TNAs don't establish a measurable baseline. They identify needs qualitatively ("managers say we need more data literacy") without quantifying the current state ("42% of analysts score below the competency benchmark on data modeling"). Without a number to start from, there's no way to measure whether the training investment closed the gap. How Skills Data Transforms TNA Skills data doesn't replace the training needs analysis. It makes every step of the process faster, more accurate, and measurable. From opinions to measurement When you have a competency framework that defines the skills each role requires and a systematic assessment process that measures people against those benchmarks, the TNA writes itself. The gap between "what the role needs" and "what the person has" is the training need — quantified, specific, and defensible. No surveys required. No stakeholder interviews about what training "feels" right. The data shows the gaps. The gaps determine the investment. From annual to continuous Skills assessments that run quarterly — or that update based on events like certifications earned, projects completed, or role changes — produce a living picture of organizational capability. The TNA isn't a project. It's a dashboard. When a new strategic initiative requires capabilities the workforce doesn't have, you don't need a three-month analysis. You query the system: how many people have this skill at the required level? Where are the gaps deepest? What development will close them fastest? From aggregate to specific Skills data maintains resolution at every level. You can see the individual gap ("Sarah is at Level 2 in data modeling, her role requires Level 4") and the organizational pattern ("67% of our analysts are below benchmark on data modeling, concentrated in the northeast region"). This specificity transforms training investments. Instead of "buy a data literacy program for the whole company," the recommendation becomes "deliver advanced data modeling training to 34 specific analysts, prioritizing the northeast team where the gap is deepest and the business impact is highest." From qualitative to measurable With a quantified baseline, you can measure training ROI in terms that matter. Before the training: average proficiency of 2.3 against a benchmark of 4.0. After the training: average proficiency of 3.4. Gap closed by 55%. Cost per proficiency point gained: $340. This is the language that earns L&D a seat at the strategy table. Not "we delivered 10,000 hours of training." Not "satisfaction scores averaged 4.2." But: we closed 55% of the measured gap in the capability the business identified as critical. Running a Skills-Based TNA: The Process Step 1: Start with strategy, not skills Before looking at any skills data, align with leadership on strategic priorities. What does the business need to accomplish in the next 12 months? What capabilities will those objectives require? This is the organizational-level analysis — and it hasn't changed. What changes is everything that follows. Step 2: Map capabilities to competency frameworks For each strategic priority, identify which job families are involved and what competencies matter most. If the strategy requires expanding into a new market, the relevant competencies might span sales (consultative selling), product (market analysis), and operations (supply chain management). This is where having a structured skills library pays off. Instead of brainstorming a list of needed skills from scratch, you map the strategy to existing frameworks and identify which competencies are most relevant. Step 3: Pull the gap data With frameworks in place and assessments completed, the gap analysis is automatic. The system shows you — by team, by role, by individual — where current proficiency falls below the benchmark. Start by assessing your organization's overall visibility into these gaps with the Skill Gap Calculator . If you can't pull this data quickly, that's a signal your infrastructure needs work before the TNA can be effective. Step 4: Prioritize by business impact Not all gaps are equal. A gap in a skill that directly affects revenue generation or strategic execution is more urgent than a gap in a nice-to-have competency. Rank gaps by: Proximity to strategic objectives Size of the gap (how far below benchmark) Number of people affected Risk if the gap stays open (project failure, compliance exposure, customer impact) Step 5: Design interventions by gap type Different gaps need different solutions. A proficiency gap of 1 level might be closed with mentoring or a stretch assignment. A 2-3 level gap likely requires formal training. A 4+ level gap might mean the skill needs to be hired rather than built. Map each prioritized gap to the most efficient intervention and connect it directly to a learning plan . The plan should specify: what skill, what current level, what target level, what intervention, and what timeline. Step 6: Measure and reassess After the training cycle, reassess. Did proficiency levels move? Did the gap close? Where did the intervention work, and where didn't it? This data feeds the next cycle — turning the TNA from an annual project into a continuous improvement loop. The Skills Matrix as TNA Infrastructure A skills matrix — whether in a spreadsheet or a dedicated platform — is the infrastructure that makes skills-based TNA possible. It maps employees against required competencies with proficiency ratings at each intersection. For organizations getting started, a skills matrix template provides the structure to run a first assessment cycle and produce gap data. Download one, customize it for your team's competencies, and run dual assessments (manager and self-assessment for the most accurate picture). The template works for teams under 50 people. Beyond that, the aggregation and analysis that make TNA valuable require a platform that can surface patterns across teams, departments, and the full organization — connecting gap data to development plans automatically rather than through manual spreadsheet analysis. From Exercise to Engine The training needs analysis has been treated as a periodic exercise for decades. An annual project. A report. A justification for budget requests. It deserves better. When skills data replaces opinion as the foundation of TNA, the exercise becomes an engine. It runs continuously. It produces specific, measurable recommendations. It connects every training dollar to a quantified gap. And it gives L&D leaders the evidence they need to prove that learning investment drives business outcomes — not just engagement scores. The organizations that figure this out first will have a compounding advantage. Every assessment cycle produces better data. Every training investment is more targeted. Every gap that closes strengthens the organization's capability to execute its strategy. Start by assessing your organization's visibility. The Skills Gap Calculator takes two minutes and tells you whether your current infrastructure can support a skills-based TNA — or whether you're still flying blind. FAQ What is a training needs analysis? A training needs analysis (TNA) is a systematic process for identifying the gap between an organization's current workforce capabilities and the skills required to meet strategic objectives. It examines needs at three levels — organizational, role-based, and individual — and produces a prioritized plan for learning interventions. How often should you conduct a training needs analysis? Traditional TNAs run annually, but skills-based approaches enable continuous analysis. Quarterly assessment cycles keep gap data current, with event-triggered updates between cycles. The annual TNA as a standalone project is being replaced by always-on gap visibility powered by skills data. What is the difference between a training needs analysis and a skills gap analysis? A skills gap analysis measures the difference between current and required skill levels. A training needs analysis is broader — it starts with strategic objectives, identifies capability requirements, uses gap analysis as an input, and produces a prioritized development plan. Skills gap analysis is a component of TNA, not a substitute for it. Why do most training needs analyses fail? Three reasons: they rely on surveys and opinions rather than measured skill data, they run on annual cycles that can't keep pace with changing requirements, and they don't establish quantified baselines that allow you to measure whether training investments actually closed the gaps. How does skills data improve training needs analysis? Skills data replaces opinion-based gap identification with measured proficiency levels against defined benchmarks. This produces specific, quantified gaps that can be prioritized by business impact, connected to targeted interventions, and measured after training to validate ROI. The TNA moves from subjective to evidence-based. What tools do I need for a skills-based training needs analysis? At minimum: a competency framework that defines required skills and proficiency levels for each role, and a systematic assessment process. A skills matrix template works for small teams. At scale, a skills intelligence platform automates the assessment, gap analysis, and development planning workflow that makes continuous TNA possible. --- ## You've Outgrown the Spreadsheet: When Skills Tracking Needs a System URL: https://skillsdb.com/blog/skills-tracking-vs-spreadsheets Every skills tracking effort starts in a spreadsheet. And honestly, for the first version, that's fine. A Google Sheet with names down the left, skills across the top, and proficiency ratings in the cells is a perfectly good starting point for a team of 10-15 people. The problem isn't starting in a spreadsheet. The problem is staying in one. The spreadsheet breaks at predictable moments. Not because the format fails — because the workflow around it does. And when it breaks, most organizations don't realize it until the data is already stale, the assessments have stopped, and the matrix is just a snapshot of a workforce that no longer exists. The Five Breaking Points 1. Nobody updates it The spreadsheet works when one person owns it and updates it regularly. That works for about 6 months. Then the owner changes roles, goes on leave, or just gets busy. The spreadsheet stops getting updated. Nobody notices for three months because nobody was actively using it. By the time someone needs it, the data is fiction. 2. Multiple versions appear Team A has their version. Team B has theirs. HR has a "master" that hasn't been reconciled with either. Three different proficiency scales are in use. When leadership asks for a cross-team view, someone spends two days merging spreadsheets that don't align. 3. Assessments stop happening In a spreadsheet, running assessments means: email everyone, ask them to update their ratings, chase the people who don't respond, manually compile the results, then update the spreadsheet. This overhead means assessments happen once — maybe twice — and then the process quietly dies. 4. It doesn't connect to anything The spreadsheet captures skills data. But it doesn't feed into development plans, career conversations, or workforce planning. The data sits in isolation, disconnected from the decisions it should inform. When training budget discussions happen, nobody references the skills matrix because it's in a different file that hasn't been updated. 5. Reporting is manual Every question requires manual analysis. "Which teams have gaps in project management skills?" means opening the spreadsheet, applying filters, cross-referencing role requirements, and building a chart. That's a 2-hour exercise. In a system, it's a dashboard click. When to Make the Switch The transition point isn't a team size number — it's a workflow threshold. You need a system when: More than one team needs skills visibility. Cross-team reporting from spreadsheets is a reconciliation nightmare. Assessments need to be regular. If you're running assessments quarterly (which you should be), the manual overhead of spreadsheet-based assessment is unsustainable. Skills data needs to inform decisions. When leadership starts asking for capability reports, or when training budget needs to connect to specific gaps, the spreadsheet can't keep up. Compliance requires it. In regulated industries, audit-ready skills documentation needs version control, access logging, and certification expiry tracking that spreadsheets can't reliably provide. What a Skills Tracking System Gives You The system doesn't just replace the spreadsheet — it enables workflows the spreadsheet couldn't support. Structured assessments at scale Proficiency assessments are pushed to employees and managers on a schedule. Reminders are automated. Completion is tracked. Results are compiled automatically. What took 2 days of email chasing now happens in a week without manual intervention. Automatic gap analysis When assessment data lands, gap analysis runs immediately — comparing current proficiency against role requirements from the competency framework . No manual calculation. No spreadsheet formulas. The gaps are visible the moment assessments complete. Connected development Each identified gap can generate a learning plan recommendation. Training isn't disconnected from skills data — it's driven by it. And when the next assessment cycle runs, you can measure whether the gap closed. Real-time reporting Manager analytics dashboards show team capability in real time. When a manager needs to know their team's strengths and gaps, the answer is a click away — not a request to HR followed by a 3-day turnaround. Historical trends A system captures assessment data over time. Quarter over quarter, you can see: which skills are improving, which are declining, which training investments are working, and where new gaps are emerging. A spreadsheet snapshot gives you now. A system gives you trajectory. The Migration Path You don't have to abandon the spreadsheet cold turkey. The practical migration looks like this: Import your existing data. Whatever you've captured in spreadsheets becomes the starting point. Don't throw it away — it's your baseline. Define the framework first. Before migrating data, define your competency framework in the system. This is the structure your skills data will live in going forward. Run a fresh assessment. Use the system for your first proper dual assessment (self + manager). This replaces the spreadsheet's stale data with current, calibrated ratings. Connect to development. Map assessment gaps to learning plans. This is the moment the skills data starts informing decisions — the thing the spreadsheet never did. Retire the spreadsheet. Once the system has one complete assessment cycle, the spreadsheet is officially historical. Don't maintain both. What About Small Teams? If you have fewer than 15 people in one location with one manager, a spreadsheet might genuinely be enough. The breaking points above hit later for small, co-located teams because the manager has direct visibility into everyone's capabilities. But the moment you hit any of these triggers — multiple teams, regulatory requirements, quarterly assessments, or leadership asking for cross-org reporting — the spreadsheet's limitations become the bottleneck. The skills matrix template is a great starting point. When you outgrow it, the data structure maps directly to platforms like SkillsDB — so nothing you've built is wasted. FAQ When should I switch from a spreadsheet to a skills tracking system? When multiple teams need shared skills visibility, when assessments need to happen quarterly, when skills data needs to connect to development plans, or when compliance requires audit-ready documentation. The trigger is workflow complexity, not team size. What is a skills tracking system? A skills tracking system is a platform that captures, manages, and analyzes workforce skills data. It supports structured assessments, automatic gap analysis, development plan generation, and reporting — replacing manual spreadsheet-based tracking with automated workflows. Can I migrate my existing spreadsheet data? Yes. Most platforms can import existing skills and proficiency data. The key is to define your competency framework first, then map your spreadsheet data to the new structure. Run a fresh assessment cycle in the system to establish current, calibrated data. How long does the transition take? For one team or department: 2-4 weeks to set up the framework, import data, and run the first assessment. For enterprise-wide migration: 2-3 months to roll out across multiple job families. Start with one team, prove value, then expand. Is a skills tracking system worth the cost for small teams? For teams under 15 with a single manager, a well-maintained spreadsheet can work. The system's value appears when you need cross-team visibility, automated assessments, connected development planning, or compliance documentation. If any of those apply, the ROI is clear. --- ## The AI Skills Gap Is Real — But Most Organizations Are Measuring It Wrong URL: https://skillsdb.com/blog/ai-skills-gap-workforce Every executive knows AI is changing work. Few can answer the question that matters: which of our people need which new skills, and how big is the gap? The World Economic Forum's 2025 Future of Jobs Report estimates that 44% of workers' core skills will change within five years. McKinsey projects that 12 million Americans will need to change occupations by 2030. These are big numbers. They make good keynote slides. They're also useless for planning — because they don't tell you anything about your specific workforce. The AI skills gap isn't abstract. It's the distance between what your workforce can do today and what it will need to do in 18 months. And that distance varies wildly by role, function, and industry. A blanket "AI training" program won't close it any more than a blanket antibiotic treats every infection. Why Generic AI Training Fails The most common response to the AI skills gap: buy an AI literacy course. Roll it out to everyone. Check the box. This approach fails for three reasons. It assumes a uniform gap. Your data science team doesn't need "Introduction to AI." Your customer support team needs something very different from your marketing team. A single course treats all gaps as identical, which none of them are. It focuses on knowledge, not capability. Understanding what a large language model is doesn't help someone use AI to transform their actual work. The gap isn't conceptual — it's practical. Can this person use AI tools to do their job better? That's the question, and a course completion certificate doesn't answer it. It doesn't connect to business outcomes. What capability does the organization need? Which roles are most affected? Where does AI augment existing skills vs. displace them? Without this strategic layer, AI training is activity without direction. What a Skills-Based Approach Looks Like AI transformation requires the same infrastructure as any capability shift — just applied to a rapidly evolving skills landscape. Step 1: Map AI impact by role family Not every role is equally affected. Some roles will use AI tools daily (marketing, engineering, data analysis). Some will be restructured around AI capabilities (customer support, content creation). Some will be minimally affected in the near term (field operations, skilled trades). Map your role families into three categories: AI-augmented: The role's core skills remain, but AI tools amplify productivity. These people need skills in prompting, workflow automation, and AI-assisted decision-making. AI-restructured: The role's core tasks change significantly. New competencies emerge. Some existing skills become less valuable. These people need reskilling, not just upskilling. AI-adjacent: The role uses AI outputs but doesn't operate AI tools directly. These people need AI literacy — understanding what AI can and can't do, enough to collaborate with AI-augmented colleagues. Step 2: Define the new competencies For each affected role family, add AI-specific competencies to your competency framework . These aren't generic — they're role-specific: A marketing analyst needs: AI-assisted data analysis, prompt engineering for content, automated reporting A software engineer needs: AI code review, AI-pair programming, ML model evaluation A customer success manager needs: AI-powered account health analysis, automated playbook execution An HR business partner needs: skills data interpretation, AI-assisted workforce modeling Step 3: Assess the current state Run proficiency assessments against the new competencies. Where are people today? For most organizations, the answer is: earlier than expected. Most people have experimented with ChatGPT. Few have integrated AI tools into their actual workflows. Even fewer can evaluate AI output quality in their domain. Step 4: Prioritize by business impact Use gap analysis to rank the biggest gaps by business impact, not by gap size. A small AI skills gap in your revenue team matters more than a large one in a function that won't use AI tools for two years. Step 5: Build targeted development paths Learning plans should be specific to each role family's AI competency gaps — not a one-size-fits-all AI course. The marketing team's AI development path looks completely different from engineering's. The Reskilling Reality Not every AI skills gap closes through training. Some require: Role redesign: The job itself changes. New responsibilities are added, old ones are automated. The job architecture needs to reflect this. Talent redeployment: People whose roles are significantly impacted may have transferable skills for roles that are growing. Skills data makes these lateral moves visible. Strategic hiring: Some AI capabilities can't be built internally fast enough. Knowing exactly which skills you're missing (from gap data) makes external hiring precise rather than speculative. Why Skills Data Is the Foundation You can't navigate the AI transformation without knowing where you're starting from. Every decision — what training to invest in, which roles to redesign, where to hire, who to reskill — depends on accurate, current skills data. Organizations that have already built skills infrastructure — competency frameworks , regular assessments, gap analysis — are in a dramatically better position to respond to AI than organizations starting from scratch. They can add AI competencies to existing frameworks, assess their workforce against the new requirements in weeks, and prioritize investments based on evidence. Organizations without that infrastructure are guessing. They'll buy generic training, hope for the best, and discover the actual gaps when projects fail or people leave. The Window The AI skills transformation isn't a decade-long journey. It's happening now, and the window for building assessment infrastructure before you desperately need it is closing. Start with one team. Define AI-specific competencies. Assess against them. Act on the gaps. The organizations that do this now will navigate the next 3 years from a position of clarity. The rest will navigate it from a position of hope. FAQ What is the AI skills gap? The AI skills gap is the distance between the AI-related capabilities your workforce currently has and the capabilities it needs to leverage AI effectively. It varies by role — some roles need AI tool proficiency, others need reskilling for restructured responsibilities, and others need AI literacy for cross-functional collaboration. How do you assess AI readiness in your workforce? Add AI-specific competencies to your competency frameworks for each affected role family. Run proficiency assessments against those competencies. The gap between current state and requirements shows exactly where development, hiring, or role redesign is needed. Should every employee get AI training? No. Different roles have different AI skills needs. AI-augmented roles need tool proficiency. AI-restructured roles need reskilling. AI-adjacent roles need literacy. A one-size-fits-all approach wastes budget on training that doesn't match actual gaps. How do you prioritize AI reskilling investment? Use gap analysis to rank AI skills gaps by business impact. Prioritize roles where AI capability directly affects revenue, efficiency, or strategic execution. A small gap in a high-impact role matters more than a large gap in a low-impact one. What is the difference between AI upskilling and AI reskilling? Upskilling adds AI capabilities to an existing role — the core job stays the same but becomes AI-augmented. Reskilling prepares people for fundamentally different work because AI has significantly changed what the role requires. Skills data tells you which intervention each person and role needs. --- ## What Is a Skills-Based Organization? (The Real Definition, Not the Buzzword) URL: https://skillsdb.com/blog/skills-based-organization "Skills-based organization" has become the phrase every HR tech company puts on their homepage. Deloitte writes reports about it. LinkedIn runs campaigns about it. Conference keynotes build entire talks around it. And somehow, despite all this attention, most organizations still make workforce decisions based on job titles, tenure, and who happens to be visible. The concept isn't wrong. The execution is stalled. And the reason is simple: most organizations are trying to become "skills-based" without building the infrastructure that makes it possible. What a Skills-Based Organization Actually Is A skills-based organization makes workforce decisions — hiring, staffing, development, succession, and compensation — based on verified skills data rather than job titles, tenure, or credentials alone. It's a structural shift in how talent decisions are made, not a branding exercise. The shift matters because job titles lie. Two people with the title "Senior Product Manager" at different companies — or even at the same company — may have wildly different capabilities. Tenure correlates poorly with competence. Credentials tell you what someone studied, not what they can do. A skills-based organization replaces these proxies with direct measurement: what can this person demonstrably do, at what level, verified through structured assessment? What It Requires Becoming skills-based isn't a mindset change. It's an infrastructure project. You need five things, and they need to be connected. 1. A skills taxonomy in your own language Not a vendor-supplied list of 50,000 generic skills. Your taxonomy. The one that uses the words your teams use, organized around how your business actually works. A skills library that reflects your organization is the foundation everything else builds on. 2. Competency frameworks for every role family Each role family needs defined skills and proficiency expectations. Competency frameworks answer: what does good look like here? Without them, "skills-based decisions" is just a nicer way of saying "vibes." 3. Verified assessment data Self-reported skills profiles are a start. Verified proficiency assessments — combining self and manager evaluation — are the standard. The data needs to be calibrated (managers agree on what Level 3 means), current (quarterly, not annual), and connected to the competency framework. 4. Gap analysis at every level Individual gaps power development conversations. Team gaps power staffing and training decisions. Organizational gaps power workforce strategy . Gap analysis is the engine that turns static skills data into dynamic decision support. 5. Connected systems Skills data that lives in one system and doesn't inform any other process isn't infrastructure — it's a filing cabinet. The skills system needs to feed into career pathways , learning plans , succession planning , hiring criteria, project staffing, and compensation benchmarks. Why Most Organizations Stall Deloitte's 2024 Global Human Capital Trends report found that 73% of organizations say skills-based practices are important. Only 10% have made significant progress. That 63-point gap isn't a motivation problem. It's an execution problem. Three things cause the stall: They start with technology, not framework. Buying a skills platform before defining your taxonomy and competency frameworks is like buying a CRM before defining your sales process. The tool becomes shelfware because there's nothing structured to put in it. They try to cover everything at once. "Let's map every skill for every role in the organization" is a 12-month project that never finishes. The organizations that make progress start with one job family, prove value, and expand. They don't connect skills data to decisions. Skills data that only lives in HR is a record. Skills data that informs who gets hired, who gets developed, who gets promoted, and how work gets staffed is infrastructure. Most organizations stop at the record. The Maturity Path No organization becomes skills-based overnight. The progression typically looks like this: Phase 1: Foundation (1-3 months) Define competency frameworks for 1-2 critical job families. Run the first round of assessments. Generate initial gap data. This is enough to inform one development cycle and demonstrate value. Phase 2: Expansion (3-6 months) Extend frameworks to additional job families. Connect gap data to learning plans . Start using skills data in career conversations and succession discussions. Build manager analytics dashboards so team leads can see their team's capability profile. Phase 3: Integration (6-12 months) Skills data informs hiring criteria, project staffing, and organizational design. Workforce strategy runs on capability data alongside headcount. The skills system becomes the system of record for what your organization can do. Phase 4: Intelligence (12+ months) Historical assessment data reveals trends. You can predict which gaps are emerging, which investments are working, and where attrition will hurt most. Skills data is as fundamental to decision-making as financial data. The Honest Take "Skills-based organization" is a useful concept that's been diluted by marketing. The idea is sound: make workforce decisions based on what people can actually do, not what their title says. The execution requires real investment in data infrastructure, assessment processes, and system integration. It's not a switch you flip. It's a capability you build. And the organizations that get there don't do it because they adopted the right software — they do it because they committed to treating skills as a first-class data asset and connected that data to every talent decision they make. FAQ What is a skills-based organization? A skills-based organization makes workforce decisions — hiring, staffing, development, succession, compensation — based on verified skills data rather than job titles, tenure, or credentials. It requires a skills taxonomy, competency frameworks, verified assessments, gap analysis, and connected systems that feed skills data into every talent decision. How do you become a skills-based organization? Start with competency frameworks for 1-2 critical job families. Run verified assessments. Generate gap data. Connect gaps to development plans and career paths. Expand to additional job families. Integrate skills data into hiring, staffing, and workforce strategy. The progression takes 12-18 months for meaningful transformation. What is the difference between a skills-based organization and traditional HR? Traditional HR makes decisions based on job titles, tenure, credentials, and manager opinions. Skills-based HR makes decisions based on verified capability data — what people can demonstrably do, measured against defined competency frameworks. The difference is evidence over assumption. Why do most organizations fail to become skills-based? Three reasons: they start with technology before defining frameworks, they try to cover the entire organization at once instead of piloting with one job family, and they don't connect skills data to actual decisions. The concept is widely accepted. The infrastructure is rarely built. What tools do you need for a skills-based organization? At minimum: a skills taxonomy, competency framework builder, assessment system, gap analysis engine, and learning plan integration. A platform like SkillsDB combines all five into a single system of record. The key is that these components are connected — isolated tools create data silos, not skills intelligence. --- ## How to Build a Training Matrix That Actually Drives Development URL: https://skillsdb.com/blog/training-matrix-how-to-build A training matrix is a grid that maps every employee to every training requirement their role carries, and records whether each one is complete, current, or overdue. It is the compliance backbone of every regulated industry and the development dashboard for every L&D team that takes training seriously. Quick reference: Training Matrix — the short version of this post, with the one table that matters. But most training matrices are backwards. They track completion — courses finished, certifications earned, hours logged — without connecting any of it to the skills those courses were supposed to develop. You end up with a matrix full of green checkmarks and a workforce with the same skill gaps it had before the training happened. The training matrix that works doesn't just track what people have done. It tracks what people can do because of it. What Is a Training Matrix? A training matrix is a structured record that maps employees (rows) to training requirements (columns) and tracks the status of each intersection: not started, in progress, complete, or expired. Each cell carries a completion date and, for anything with a shelf life, an expiration date. The matrix answers three questions at a glance: who is required to hold which training, who actually holds it today, and where the gaps and expirations are. In regulated environments — manufacturing, healthcare, energy, data centers, government — it is an audit artifact, because auditors need documented evidence that the person doing the work was qualified to do it. In less regulated environments it is the L&D team's operational view of coverage. The distinction that matters is between a training matrix and a skills matrix: the first tracks learning activity, the second tracks demonstrated capability. The best systems connect the two, so a skill gap traces to a training plan, to completion, to a verified change in proficiency. Training Matrix vs. Skills Matrix vs. Competency Matrix The three get used interchangeably. They shouldn't be. Training matrix Skills matrix Competency matrix Tracks Training activities completed Proficiency in specific skills Proficiency against role-level competency definitions Unit Course, certification, sign-off Skill at a proficiency level Competency (a cluster of skills and behaviors) at a level Answers Who has been trained on what, and is it current? Who can do what, and how well? Who meets the bar for this role? Decays Yes, via expiration dates Yes, via reassessment Yes, via reassessment Owner Training / compliance L&D / managers HR / talent A training matrix tracks inputs. A skills matrix tracks outcomes. A competency matrix rolls skills up to the role. You need the first for the audit and the second two for the business, and the value shows up when they share the same underlying data. Building a Training Matrix: Step by Step Step 1: Define training requirements by role Before tracking completion, define what training each role requires. Group requirements into three buckets: Mandatory and compliance: Required by regulation, policy, or safety standards. Non-negotiable, and almost always carrying a renewal date. Role-specific: Training that builds the competencies defined in your competency framework . Connected to specific skills at specific proficiency levels. Development: Elective training aligned to career growth — closing the gap between current skills and the requirements of a target role. Requirements belong to roles, not to people. When someone changes role, their requirements should change with them without anyone rebuilding a row by hand. Step 2: Map employees to requirements Create the matrix: rows are employees, columns are training requirements. For each cell, track completion status, completion date, expiration date where one applies, and — if the training is connected to skills data — the resulting proficiency change. Step 3: Identify gaps and priorities The matrix immediately reveals three things: compliance risk (training that is expired or approaching expiration), coverage gaps (required training that hasn't started), and development opportunities (skills-aligned training that would close the biggest proficiency gaps ). Prioritize in that order. Compliance first, because it is non-negotiable. Role-specific gaps second, because they affect performance now. Development training third, because it compounds over time. Step 4: Connect to skills data This is the step most organizations miss — and it is the one that turns a training matrix from a compliance checklist into a development engine. When training completion connects to proficiency assessment , you can measure whether the training worked. Did the person's assessed proficiency in the target skill improve after the course? If yes, the investment paid off. If not, the course was the wrong intervention for that gap, and the matrix just told you so. Learning plans generated from gap data ensure every training assignment traces back to a specific, measured deficit — not a catalog browse or a manager's guess about what the team needs. Step 5: Automate and maintain A training matrix that requires manual updates will decay. Within six months it will be incomplete. Within a year it will be abandoned. The maintenance burden determines the format. Under 20 people, a spreadsheet works if one person owns it and updates it weekly. Between 20 and 100, you need automated reminders for expiring certifications, manager self-service for recording completion, and a dashboard view. Past 100, the training matrix has to integrate with your LMS, HRIS, and skills platform to stay current without human intervention. Training Matrix for ISO 9001 and Regulated Operations In manufacturing, healthcare, energy, data centers, and government, the training matrix isn't optional. It is the artifact the auditor asks for. ISO 9001 clause 7.2 requires an organization to determine the competence needed for work that affects quality, ensure people are competent on the basis of education, training, or experience, take action where they aren't, and retain documented evidence of all of it. AS9100, IATF 16949, ISO 13485, FDA 21 CFR Part 11, and the FAA's repair-station rules make the same demand in their own vocabulary. A spreadsheet of completion dates satisfies none of them on its own, because the finding is never "you didn't train people." The finding is "you can't prove the person who executed this procedure was competent against the revision in force on that date." A training matrix built for a regulated operation carries four things a general-purpose one doesn't: Revision-linked training. Every requirement points at a specific revision of a specific SOP, work instruction, or standard. When the document changes, the requirement resets and the cell goes red until retraining is recorded. Expiration and currency. Certifications carry expiry dates. Operational skills carry recency requirements. Both surface before they lapse, not after the auditor finds them. Evidence, not just status. Each completion links to who delivered the training, who signed it off, what assessment verified it, and the score or observation that resulted. An immutable audit trail. Changes are timestamped and attributed. The answer to "show me everyone currently qualified against revision 4 of this SOP" is the same whether the auditor asks today or six months from now. Auditors check three things: coverage (does every employee have documented training for their role requirements?), currency (is it current, not expired?), and traceability (who trained them, when, and with what outcome?). A certification tracking system handles all three — flagging expirations before they happen, keeping audit-ready records, and tying training to the role requirements that demand it. Training approvals close the loop on sign-off so the evidence exists at the moment of completion rather than being reconstructed later. For frontline training — factory floors, job sites, data halls, clinical units — the matrix has to be usable by supervisors in the field, not just HR at headquarters. Mobile access and role-filtered views are what make compliance manageable when the workforce is distributed across shifts and sites. Three Worked Examples A manufacturing plant Rows are 340 operators across three shifts. Columns are safety training (lockout-tagout, forklift, confined space), machine-specific qualifications tied to work-instruction revisions, and quality procedures. Lockout-tagout renews annually. When the plant revises WI-207 for the new press line, 42 cells turn red the same day, and the shift supervisor sees exactly who can't run the line until retraining is recorded. The audit answer for "who was qualified on WI-207 rev C on March 12" is a filter, not a week of spreadsheet archaeology. A data center operations team Rows are 120 technicians across four sites. Columns are vendor certifications (UPS, generator, chiller, fire suppression), internal method-of-procedure qualifications, and electrical safety training with hard expiry dates. The matrix is what proves to a hyperscale customer's auditor that the technician who performed a critical switching operation at 02:00 held current qualification for that procedure on that equipment. Certification expiry is the operational risk: one lapsed generator cert on a site with two qualified technicians is a single point of failure the matrix makes visible weeks ahead. A hospital unit Rows are 85 nurses and technicians. Columns are licensure, unit-specific competencies (ventilator management, medication administration, infusion pumps by model), and annual mandatory training. The matrix connects to competency validation: completing the pump in-service is a training record, but the annual observed skills check is what proves competence, and the matrix shows both. When a new pump model arrives, the requirement is added once at the unit level and 85 rows update. The Template A practical training matrix template includes an employee roster with roles and departments, a training catalog organized by requirement type (compliance, role-specific, development), a completion grid with status, dates, and expiration tracking, and a gap dashboard showing which employees have outstanding requirements. Build yours with our skills matrix tool — it includes a training tracker tab alongside the skills proficiency grid, so the two views share one set of data from day one. Training Is the Input. Competence Is the Output. A training matrix that only records completion measures effort. A training matrix connected to skills data measures whether the effort changed anything. Regulators have understood the difference for decades, which is why they ask for competence evidence and not attendance sheets. The matrix that satisfies them is the same matrix that makes development real: it starts from what the role requires, tracks what was done about it, and closes with proof that the person can now do the work. FAQ What is a training matrix? A training matrix maps employees to the training requirements of their roles and tracks the status of each one: not started, in progress, complete, or expired. It records completion and expiration dates, surfaces coverage gaps, and in regulated industries serves as the documented evidence auditors require that people were qualified for the work they performed. What is the difference between a training matrix and a skills matrix? A training matrix tracks learning activities — courses completed, certifications earned, hours logged. A skills matrix tracks demonstrated capability — what people can actually do and at what proficiency level. The training matrix records inputs and the skills matrix records outcomes. Connecting them is how you find out whether training actually improved capability. How often should a training matrix be updated? Continuously for compliance training, where certifications and mandatory requirements should track automatically against their expiry dates. Monthly for role-specific training and quarterly for development training reviews. The right frequency follows from the consequence of stale data; in a regulated operation an outdated matrix is an audit finding waiting to happen. Does a training matrix satisfy ISO 9001 clause 7.2? Only if it holds evidence, not just status. Clause 7.2 requires you to determine the competence needed, ensure people have it, act where they don't, and retain documented evidence. A matrix that links each completion to the SOP revision, the trainer, the sign-off, and an assessment result meets that bar. A grid of completion dates on its own does not. How do I connect training to skills development? Link each training requirement to the specific skill and proficiency level it targets. After completion, reassess the employee's proficiency in that skill. The change between the pre-training and post-training assessment is your measure of training effectiveness, and it tells you which courses actually close gaps and which ones only fill calendars. When does a training matrix outgrow a spreadsheet? Around 20 to 30 people, or the moment more than one person needs to update it. Past that point, expiration reminders, supervisor self-service, revision-linked requirements, and an audit trail stop being nice-to-haves. If your operation is regulated or spread across shifts and sites, the spreadsheet fails earlier, usually during the first audit. --- ## Succession Planning That Actually Works: A Skills-Based Approach URL: https://skillsdb.com/blog/succession-planning-skills-data Most succession planning is a spreadsheet with names on it. Someone in HR maintains a list of "high potentials" matched to critical roles, updates it once a year, and files it until the next leadership review. Then a key person leaves, and the list turns out to be fiction — the named successors aren't ready, the assessment was subjective, and the organization scrambles to hire externally for a role it should have filled internally. This isn't a people problem. It's a data problem. Succession planning fails when it runs on opinions instead of evidence. The Broken Model Traditional succession planning asks managers: "Who could replace you if you left?" The answers are biased by recency, familiarity, and office proximity. They rarely account for specific capability gaps between the successor and the role requirements. And they're almost never validated against structured assessment data. The result is a bench that looks strong on paper but isn't ready in practice. Harvard Business Review's research on CEO succession found that 40% of internal CEO transitions underperform expectations — often because readiness was assumed rather than measured. Skills-Based Succession Planning Skills-based succession planning replaces subjective nomination with objective measurement. Instead of "who does the manager think is ready?" it asks: "who has the closest skills match to the role requirements, and what specific gaps need to close?" This requires three things: 1. Clear role requirements Every critical role needs a defined competency framework — not a job description, but a specific list of skills and proficiency levels required for success. What does the VP of Engineering need to be able to do, at what level? 2. Assessed candidates Potential successors need current proficiency assessments against those same competencies. Not performance ratings. Not manager impressions. Structured skill-level data that can be compared to role requirements. 3. Gap visibility The delta between a successor's current skills and the role's requirements is the succession gap . Making that gap visible — and specific — transforms succession from a name on a list to a development plan. The Five-Step Process Step 1: Identify critical roles Not every role needs a succession plan. Focus on positions where a vacancy would significantly impact operations, revenue, or strategy. Typically 10-15% of roles qualify as critical. Step 2: Define success profiles For each critical role, define the competency framework : 8-12 competencies with expected proficiency levels. This is the benchmark successors will be measured against. Step 3: Identify and assess candidates Cast a wider net than the obvious picks. Use skills data to find candidates across the organization — not just the direct reports of the current incumbent. A skills library search might surface candidates in adjacent functions that a manager-only nomination process would miss. Assess candidates against the success profile. Dual assessment (self + manager) gives the most reliable data. Step 4: Map readiness For each candidate-role pairing, calculate the gap between current proficiency and role requirements. Categorize readiness: Ready now: Gaps are minimal (1 level or less on most competencies). Could step in within 3 months. Ready in 12 months: Has the foundation. Specific development targets can close remaining gaps. Developing (24+ months): High potential but significant gaps remain. Needs structured development and stretch assignments. Step 5: Build development plans For each successor, create targeted learning plans that address the specific gaps between their current skills and the role requirements. Not generic leadership training — specific, measurable development tied to named competencies and proficiency targets. Track progress quarterly through reassessment. Readiness should improve measurably over time. Why This Approach Works Skills-based succession planning produces three outcomes the traditional model can't: Objectivity. Readiness is measured, not assumed. Two different leaders reviewing the same data would reach the same conclusion about a candidate's readiness. Specificity. Instead of "Sarah is a high potential," you have "Sarah is at Level 3 in strategic planning — the role requires Level 4. Her development plan targets this gap through a cross-functional strategy project in Q3." Breadth. When you search for successors by skills match rather than manager nomination, you find candidates you would have overlooked. Internal mobility increases. Diversity in succession pipelines improves. Connecting Succession to Workforce Strategy Succession planning shouldn't exist in isolation. It's a component of workforce strategy — and the data it generates informs broader decisions. If your succession analysis reveals that three critical roles have no ready-now candidates, that's a workforce planning signal. It might mean accelerating internal development, adjusting hiring priorities, or restructuring to reduce single-point-of-failure risk. Manager analytics dashboards that show bench strength by team and role give leadership a real-time view of organizational resilience — not an annual report that's outdated by the time it's presented. FAQ What is skills-based succession planning? Skills-based succession planning identifies and develops successors for critical roles using structured competency data rather than subjective manager nominations. It measures the specific skills gap between potential successors and role requirements, then builds targeted development plans to close those gaps. How is skills-based succession planning different from traditional succession planning? Traditional succession planning relies on manager opinions about who's "ready." Skills-based succession planning uses proficiency assessments against defined competency frameworks to objectively measure readiness, identify specific gaps, and track development progress over time. How many roles need succession plans? Focus on critical roles — positions where a vacancy would significantly impact operations, revenue, or strategy. Typically 10-15% of roles in an organization qualify. Starting with the top 10-20 most critical roles is enough to demonstrate value and build the process. What data do you need for succession planning? A competency framework for each critical role (skills + proficiency requirements), current proficiency assessments for potential successors, and the ability to calculate and track the gap between the two. This data enables objective readiness measurement and targeted development planning. How often should succession plans be reviewed? Quarterly reassessment keeps the data current. Annual reviews are too infrequent — people develop, leave, or change roles between reviews. Quarterly cadence ensures readiness data reflects actual capability, not a stale snapshot. --- ## What Is Skills Intelligence? (and Why Tracking Alone Isn't Enough) URL: https://skillsdb.com/blog/what-is-skills-intelligence Every HR tech vendor talks about skills. Skills tracking. Skills taxonomies. Skills ontologies. AI-powered skills inference. The vocabulary has exploded, but the substance hasn't kept pace. Here's the distinction that matters: most organizations track skills. Very few have skills intelligence. Tracking tells you what exists. Intelligence tells you what to do about it. The Difference Between Tracking and Intelligence Skills tracking is a database. It records which employees have which skills, often through self-reported profiles, resume parsing, or annual review checkboxes. It answers the question: "What skills do we have?" Skills intelligence is a decision engine. It connects skills data to business outcomes — answering questions like: Which teams have the biggest capability gaps relative to next quarter's priorities? Who's ready for a leadership role? Where should we invest our training budget for maximum impact? If these 10 people leave, what capabilities do we lose? The gap between these two is enormous. And most organizations that think they have skills intelligence actually have skills tracking with better reporting. What Makes Skills Data "Intelligent" Skills data becomes intelligence when it meets four criteria: 1. It's verified, not self-reported Self-reported skills profiles are unreliable. People overestimate skills they enjoy and underestimate skills they use unconsciously. A proficiency assessment that combines self-assessment with manager evaluation produces calibrated data — data you can make decisions from. 2. It's structured against a framework Skills data without a competency framework is just a list. Intelligence requires structure: what skills matter for which roles, at what proficiency level, organized into a taxonomy that reflects how your organization actually works. 3. It connects to decisions Skills data that lives in a silo — even a well-organized silo — isn't intelligence. Intelligence means the data flows into gap analysis , learning plans , succession planning , workforce strategy , and every talent decision in between. 4. It's current Skills data has a half-life. People develop new capabilities, existing skills atrophy, roles evolve, organizational priorities shift. Data from last year's annual review is already outdated. Skills intelligence requires assessment cadences that keep the data fresh — quarterly at minimum. Why Skills Intelligence Matters Now Three forces are converging to make skills intelligence urgent rather than aspirational. The skills landscape is shifting faster than ever. World Economic Forum's 2025 Future of Jobs Report estimates that 44% of workers' core skills will change within five years. Organizations that can't see their current capabilities can't anticipate what they'll need. AI is restructuring work. Roles aren't disappearing wholesale — they're being reshaped. Understanding which skills are augmented by AI, which are displaced, and which become more valuable requires granular workforce data, not job title analysis. AI transformation strategies built without skills intelligence are guesswork. Internal mobility is a competitive advantage. Organizations that can match internal talent to open roles based on verified skills — not just job history — fill positions faster, retain more people, and spend less on external recruiting. But internal mobility requires knowing what people can actually do, not what their title implies. The Skills Intelligence Stack A complete skills intelligence system has five layers: Layer What it does Example Skills Library Defines the taxonomy — what skills exist and how they're categorized Skills Library Competency Framework Sets expectations — what skills each role needs, at what level Competency Frameworks Assessment Captures current state — verified proficiency for each person Proficiency Assessment Gap Analysis Calculates the delta — where gaps exist at every level Gap Analysis Decision Layer Connects data to action — development, staffing, planning Manager Analytics Most tools cover one or two layers. A skills intelligence platform covers all five — and the value comes from the connections between them, not from any single layer. From Tracking to Intelligence: The Progression You don't jump from tracking to intelligence overnight. The progression follows a predictable path: Stage 1: Inventory. You know what skills exist in your workforce. This is table stakes — and most organizations don't have even this. Stage 2: Assessment. You know how proficient people are, based on calibrated assessment data, not self-reports or assumptions. Stage 3: Gap visibility. You can see where the gaps are — at the individual, team, and organizational level — ranked by business impact. Stage 4: Connected decisions. Skills data drives training allocation, career pathing, succession planning, hiring priorities, and strategic workforce planning. Every talent decision is informed by verified capability data. Stage 4 is skills intelligence. Everything before it is a prerequisite. The Compounding Value Skills intelligence compounds. The first assessment cycle gives you a snapshot. The second gives you a trend. The third gives you predictive power — you can see which gaps are closing, which are widening, and where new ones are emerging before they become critical. This is what turns skills from an HR initiative into business infrastructure. When the CFO asks "can we execute this strategy with the team we have?" — skills intelligence gives you a quantified answer, not an opinion. FAQ What is skills intelligence? Skills intelligence is the practice of collecting, verifying, and analyzing workforce skills data to drive decisions about hiring, development, succession, and workforce planning. Unlike skills tracking (which records what skills exist), skills intelligence connects proficiency assessments, gap analysis, and career frameworks into a system that informs every talent decision. What is the difference between skills tracking and skills intelligence? Skills tracking records what skills employees have. Skills intelligence uses that data to identify gaps, predict future needs, align training to strategy, and inform staffing decisions. Tracking is a database. Intelligence is a decision engine. What is a skills intelligence platform? A skills intelligence platform is software that integrates the full skills data stack: skills taxonomy, competency frameworks, proficiency assessments, gap analysis, and decision support (analytics, career pathing, succession planning). It serves as the system of record for workforce capability data. Why is skills intelligence important? Skills intelligence enables organizations to allocate training budgets to actual gaps, staff projects with the right people, plan succession based on verified readiness, and adapt workforce strategy to changing skill demands. Without it, these decisions are based on assumptions. How do you build skills intelligence in an organization? Start with a competency framework for one job family. Run calibrated assessments (self + manager). Generate gap data. Connect gaps to learning plans and career paths. Expand to additional job families. The goal is to reach a state where skills data informs every talent decision, not just development planning. --- ## Workforce Planning Needs Skills Data, Not Just Headcount URL: https://skillsdb.com/blog/workforce-planning-with-skills-data Most workforce planning runs on two inputs: headcount and budget. How many people do we have? How many do we need? What will it cost? This is necessary. It's also insufficient. Headcount tells you how many bodies occupy roles. It tells you nothing about whether those bodies have the capabilities you need for next year's strategy. You can be fully staffed and critically under-skilled at the same time — and many organizations are, without knowing it. Skills-based workforce planning adds a third dimension: capability. Not just how many people you have, but what they can do, where the gaps are, and what that means for your ability to execute. The Headcount Trap The classic workforce planning cycle goes like this: leadership sets strategic priorities. HR translates those priorities into headcount plans. Recruiting fills the positions. Finance approves the budget. The plan is "complete." But three things this model can't answer: Can our current workforce execute the strategy? Having 500 engineers doesn't mean you have the capabilities for an AI transformation. You might have 500 people trained in legacy systems and zero people with ML expertise. Headcount says you're fine. Capabilities say you're exposed. Where should we invest in development vs. hiring? If your team is one proficiency level away from having a critical capability, training is faster and cheaper than hiring. If the gap is three levels, hire. Headcount planning can't make this distinction because it doesn't see capability. What happens when key people leave? Attrition planning based on headcount says: backfill the role. Capability planning says: this person was the only one with advanced system architecture skills — losing them creates a capability gap that affects three projects, and the replacement needs these specific competencies. What Skills-Based Workforce Planning Looks Like Skills-based workforce planning layers capability data on top of the traditional headcount model. It answers four questions: What capabilities do we have today? A skills library and proficiency assessment program gives you a current-state inventory — not what job titles suggest, but what people can demonstrably do. Aggregated by team and department, this is your capability baseline. What capabilities do we need for our strategy? Strategic initiatives require specific capabilities. An AI transformation needs data engineers, ML engineers, and people who can translate between technical and business teams. A new market entry needs people with regulatory expertise, local market knowledge, and cross-cultural communication skills. Map strategic initiatives to required capabilities — the same way you'd map them to required headcount, but at the skill level. Where are the gaps? Gap analysis at the organizational level shows the delta between current capabilities and strategic requirements. Not in aggregate ("we need more tech talent") but in specifics ("we need 12 more people with Level 3+ cloud architecture skills, and our current team of 8 averages Level 1.5"). What's the plan? For each capability gap, there are three plays: Build: Develop existing employees through targeted learning plans . Fastest for closing 1-2 level gaps. Buy: Hire externally. Necessary for capabilities that don't exist internally or would take too long to develop. Borrow: Contractors, consultants, or cross-functional redeployment for short-term needs. The mix depends on timeline, budget, and gap size — decisions that are impossible to make without skills data. The Organizational View When workforce strategy runs on skills data, leadership gets visibility they've never had: Capability heatmaps: Which departments are strongest and weakest on the skills that matter for next year? Bench strength dashboards: For critical roles, who's ready now, who's 12 months away, and where are the gaps? Attrition modeling: If projected turnover hits 15% in engineering, what capabilities are at risk? What's the replacement cost in skills terms, not just salary? Investment ROI: Are our training investments actually closing the gaps that matter? Manager analytics can show this quarter over quarter. This is what separates workforce planning from workforce strategy. Planning counts people. Strategy develops capabilities. Getting Started You don't need perfect data to start. You need: One strategic priority that depends on specific capabilities A competency framework for the teams involved Current assessments against that framework Gap data that shows the distance between current state and strategic need That's enough to make one workforce planning cycle smarter than any headcount-only approach. And once you've done it once, the value case for expanding is obvious. FAQ What is skills-based workforce planning? Skills-based workforce planning adds capability data to traditional headcount planning. Instead of only counting people and budgets, it maps the specific skills your workforce has, compares them to the capabilities your strategy requires, and identifies gaps that need to be closed through development, hiring, or external resources. How is workforce planning different from workforce strategy? Workforce planning typically focuses on headcount — how many people, in which roles, at what cost. Workforce strategy incorporates capability — what skills those people need, where gaps exist, and how to build organizational resilience. Planning is operational. Strategy is directional. What data do you need for skills-based workforce planning? A competency framework defining required skills by role, current proficiency assessments for your workforce, gap analysis showing the delta between current and required capabilities, and the ability to model scenarios (attrition impact, development timelines, hiring needs). How do you connect workforce planning to training investment? Map each identified capability gap to a response: build (training), buy (hiring), or borrow (contractors). For build responses, connect the specific skill gap to a learning plan with measurable proficiency targets. Track whether training investments actually close the gaps through quarterly reassessment. Can workforce planning be done with spreadsheets? For a single team or department, yes. For enterprise-scale planning across multiple business units, spreadsheets break down — the data is too complex, too dynamic, and too interconnected. A platform that integrates skills data, gap analysis, and scenario modeling is necessary for workforce strategy at scale. --- ## What Is Skills Gap Visibility? (and How to Score Yours) URL: https://skillsdb.com/blog/what-is-skills-gap-visibility Ask any CHRO whether their organization has skill gaps. The answer is always yes. Now ask a harder question: which teams have the biggest gaps, and what's the dollar cost of leaving them open? That second question usually gets silence — or a request for two weeks and a spreadsheet project. The gap itself isn't the problem. The blindness is. Most organizations treat skill gaps as a training issue. Buy more courses. Roll out another LMS module. Send people to conferences. But you can't fix what you can't see. And most companies can't see their skill gaps with any precision at all. They know gaps exist the way you know your roof will need replacing someday — vaguely, without urgency, until it starts raining. This is a visibility problem, not a skills problem. And it has a name. What Is Skills Gap Visibility? Skills gap visibility is the degree to which an organization can see, measure, and act on the difference between the skills its workforce has and the skills it needs. It encompasses four capabilities: knowing what skills exist in your workforce today, identifying where gaps sit at the individual and team level, connecting development investments to those specific gaps, and using skills data to inform strategic workforce decisions. Organizations with high skills gap visibility don't just track skills — they operationalize the data. Those with low visibility are making training investments, hiring decisions, and workforce plans based on assumptions rather than evidence. The concept moves beyond simple skills tracking to measure whether skill data actually reaches the people who make decisions — and whether those decisions are better because of it. The Four Dimensions of Skills Gap Visibility Skills gap visibility isn't a single metric. It breaks down into four dimensions, each measuring a different layer of organizational capability. 1. Skills Inventory Do you know what skills your workforce has right now? Not what their job descriptions say. Not what their resumes listed when they were hired. What they can actually do today. Most organizations have a fragmented picture at best. Skills data lives in spreadsheets, HRIS fields that haven't been updated in two years, and the heads of managers who know their teams. McKinsey's 2024 research on workforce transformation found that only 28% of organizations have a comprehensive, up-to-date view of their workforce capabilities. A strong skills inventory means you can search for any skill across the organization and get accurate, current results. A weak one means you're asking around on Slack when a project needs a specific capability. 2. Gap Visibility Can you see where the gaps sit? Not in aggregate — at the team and individual level? This is where most organizations stall. They might run annual performance reviews that surface some skill gaps as side effects. They might have a general sense that their data science team needs upskilling. But they can't produce a dashboard that shows: here are the 12 teams with the most critical gaps, ranked by business impact. Gap visibility requires two things: a clear definition of what skills each role needs (a competency framework ) and a systematic way to assess people against that benchmark (like dual manager-self assessments ). 3. Development Alignment Is your training spend connected to your actual skill gaps? LinkedIn's 2024 Workplace Learning Report found that organizations spend an average of $1,220 per employee on training annually. The question is whether that investment targets the right gaps. In organizations with low development alignment, training decisions are driven by vendor catalogs, manager requests, or employee interest surveys — not gap data. Content gets consumed. Completion rates look healthy. But the gaps that matter most to the business stay open. High development alignment means every dollar of training spend can be traced back to a specific, measured gap. Learning plans are generated from assessment data, not from a content library browse. 4. Decision Readiness Can leadership make workforce decisions using skills data? This is the dimension that separates skills tracking from skills intelligence. Decision readiness means the CHRO can walk into a board meeting and say: here's our bench strength for the three roles most critical to next year's strategy. Here are the gaps. Here's what we're doing about them. Gartner's 2024 HR Technology Survey reported that 76% of HR leaders say they struggle to provide workforce insights that influence strategic business decisions. That's a decision readiness problem. The data either doesn't exist, isn't trusted, or isn't accessible in a format that executives can act on. The Skills Gap Visibility Maturity Model Based on these four dimensions, organizations fall into one of four tiers. The Skills Gap Calculator scores your organization across all four dimensions and places you on this maturity model. Flying Blind (Score: 0-25) Your organization has significant skills visibility gaps. Workforce decisions — hiring, training, promotions, project staffing — are made on intuition, manager opinion, and institutional memory. Skill gaps surface only when something goes wrong: a project fails, a key person leaves, or a compliance audit finds a deficiency. Organizations at this tier typically track skills informally or not at all. When they do invest in training, the connection between the investment and the organization's actual gaps is circumstantial at best. Partial View (Score: 26-50) You have some skills awareness, but the picture is incomplete. Some teams track skills in spreadsheets. Annual reviews surface some gaps. Training decisions are partly informed by manager feedback. But there's no unified view, and the data that exists is often stale. The defining characteristic of this tier: you know gaps exist, but you can't quantify them with confidence. Training investments feel directionally right but can't be validated against measured gaps. Getting Clearer (Score: 51-75) You're ahead of most organizations. Skills data exists in a structured format. Assessment processes are in place. Leadership has some access to skills insights. But gaps remain between the data you collect and the decisions you make. Organizations at this tier often have the right tools but haven't closed the loop. They assess skills but don't systematically connect gap data to development plans. Or they have great team-level visibility but can't aggregate it for strategic workforce planning. Skills Intelligent (Score: 76-100) Your skills visibility is strong. Skills data is current, comprehensive, and connected to decisions at every level — from individual development plans to board-level workforce strategy. Training investments are directly tied to measured gaps. Leadership uses skills data as a core input for hiring, succession, and organizational design. The question at this tier isn't whether you have visibility — it's whether your tools can scale with growing organizational complexity. Organizations that reach this level have typically moved beyond spreadsheets and bolt-on HRIS features to a purpose-built skills platform that serves as the system of record. Why Visibility Matters More Than You Think The cost of low skills gap visibility shows up in three places most organizations don't measure. Wasted training spend The Association for Talent Development's 2024 State of the Industry report found that organizations spend an average of $1,267 per employee per year on training. Without visibility into actual gaps, a significant portion of that investment targets skills people already have, skills that aren't business-critical, or skills delivered in formats that don't stick. You can't calculate the waste if you can't see the gaps. Slow internal mobility When you can't see what skills people have, you can't match them to open roles. Organizations with low visibility default to external hiring for capabilities that already exist internally — a problem a resume search powered by skills data can solve instantly. Deloitte's 2024 Global Human Capital Trends report found that 73% of organizations say internal mobility is important, but only 22% feel effective at it. Visibility is the gap between aspiration and execution. Delayed workforce planning Every strategic planning cycle that begins with "we need to understand our current capabilities" is starting from zero. Organizations with high visibility don't have a discovery phase — they have a dashboard. Workforce strategy moves at the speed of the data. The time saved isn't measured in hours. It's measured in quarters of faster response to market shifts. How to Measure Your Skills Gap Visibility The Skills Gap Calculator is a 7-question diagnostic that scores your organization on a 0-100 scale across all four dimensions. It takes two minutes and gives you an immediate, color-coded assessment of where you stand — and where the gaps in your visibility sit. The questions cover how you track skills, how you identify gaps, whether training is connected to gap data, and whether leadership can make decisions from skills insights. Each dimension gets its own score so you can see exactly which layers need work. Your overall score places you on the maturity model and identifies your two weakest dimensions. For most organizations, the eye-opener isn't the overall score — it's the dimension breakdown. You might have a decent skills inventory but zero development alignment. Or strong gap visibility at the team level but no decision readiness at the leadership level. From Visibility to Intelligence Seeing your gaps is the first step. Acting on them is where the value compounds. The path from Flying Blind to Skills Intelligent isn't a technology purchase — it's a capability build. It starts with defining competencies in your organization's own language, not adopting a pre-built taxonomy that looks impressive in a demo but doesn't match how your teams actually work. It moves through systematic assessment — manager and self-assessment paired together — to produce gap data you can trust. And it culminates in connecting that data to every workforce decision: who gets trained on what, who's ready for promotion, which teams need reinforcement before next quarter's initiative. SkillsDB was built for this progression. The platform serves as the system of record for skills data, connects gap analysis to learning plans , and surfaces insights through manager analytics dashboards that make decision readiness the default, not the aspiration. But the starting point isn't the platform. It's the diagnosis. Until you know your score, you're guessing about the guessing. Take the Skills Gap Calculator and find out where you stand. FAQ What is skills gap visibility? Skills gap visibility is the degree to which an organization can see, measure, and act on the difference between the skills its workforce has and the skills it needs. It encompasses four dimensions: skills inventory, gap visibility, development alignment, and decision readiness. Organizations with high visibility use skills data to drive training investments, staffing decisions, and strategic workforce planning. How do you measure skills gap visibility? The Skills Gap Calculator scores organizations on a 0-100 scale across four dimensions. Seven diagnostic questions assess how you track skills, identify gaps, connect training to gap data, and use skills insights for decisions. The output places you on a four-tier maturity model and identifies your weakest dimensions. What is the difference between skills tracking and skills gap visibility? Skills tracking is the act of recording what skills employees have. Skills gap visibility goes further — it measures whether you can see where gaps exist, whether training is connected to those gaps, and whether leadership can make workforce decisions using the data. An organization can track skills diligently and still have low visibility if that data never reaches decision-makers. Why do most organizations have low skills gap visibility? Three common causes: skills data is fragmented across spreadsheets, HRIS fields, and manager knowledge; assessment processes are informal or annual rather than systematic; and the gap between collected data and decision-making is wide. Most organizations invest in training without a clear line of sight to the gaps that matter most. What score do most organizations get on the Skills Gap Calculator? Based on early assessments, the majority of organizations score between 20 and 45, placing them in the "Flying Blind" or "Partial View" tiers. The most common weakness is decision readiness — even organizations that track skills reasonably well struggle to connect that data to strategic workforce decisions. How can I improve my organization's skills gap visibility? Start by assessing where you are — take the Skills Gap Calculator. Then focus on your weakest dimension. If skills inventory is the gap, begin with competency frameworks and structured assessments. If development alignment is weak, connect your gap data to learning plans. If decision readiness is low, build dashboards that surface skills insights for leadership. --- ## Skills-Based Career Pathing: Build Pathways People Actually Follow URL: https://skillsdb.com/blog/skills-based-career-pathing Most career ladders are fiction. They show a vertical chain of job titles — analyst to senior analyst to manager to director — without explaining what actually changes between levels. No skill requirements. No measurable thresholds. No clarity on what "ready for the next step" means in practice. Career pathing is the process of mapping clear, skills-defined progression routes that show employees exactly what capabilities they need to develop in order to advance — replacing vague title hierarchies with navigable pathways grounded in real competency data. When career paths are specific and visible, people stay. When they're abstract, people leave. LinkedIn's 2024 Workplace Learning Report found that employees who see clear career growth opportunities are 2.2x more likely to remain with their employer. Why Do Traditional Career Ladders Break Down? The standard career ladder assumes progression is vertical and uniform. Everyone moves up the same chain, at roughly the same pace, through the same titles. But that's not how careers work — and it's not how organizations need them to work. A senior engineer might be more valuable deepening their technical expertise than moving into management. A marketing specialist might want to shift into product management, not just become a marketing manager. The ladder model can't accommodate lateral movement, skill-based progression, or non-linear career paths. The deeper problem is that traditional ladders are title-driven, not skill-driven. When you ask "what does it take to get promoted?" and the answer is vague — "demonstrate leadership" or "show strategic thinking" — employees have nothing concrete to work toward. They're left guessing, and guessing erodes engagement. Map pathways to skills, not titles Skills-based career pathing starts with a different question: instead of "what's the next title?" it asks "what skills define each level, and where does this person stand today?" This requires two things most organizations lack: a clear competency framework for each role family, and current skills data on every employee. Without both, career pathing remains theoretical. Start with job families. Group roles that share a core skills DNA. Software engineering, customer success, operations, sales — each family has a distinct progression logic. Define the skills that matter at each level within the family, with specific proficiency expectations . A junior data analyst might need SQL at a Level 3; a senior analyst needs it at Level 5, plus statistical modeling at Level 3. Make the paths visible. A career pathway that lives in an HR system nobody checks is no better than the old ladder. Employees need to see their current skills assessment , the requirements for roles they're interested in, and the specific gaps between where they are and where they want to go. That visibility is what turns career development from an annual review conversation into an ongoing, self-directed process. Enable lateral movement. The most powerful thing about skills-based pathing is that it reveals unexpected connections. An operations manager might be 80% of the way to a project management role based on their existing skills. A customer success rep might have the analytical foundation for a solutions engineering path. When career pathways are defined by skills rather than titles, these transitions become visible and achievable. Use skills data to close the navigation gap The gap between "here's your career path" and "here's how to actually get there" is where most career development programs stall. Skills data bridges that gap. When you know exactly which skills an employee needs to develop — and at what proficiency level — you can connect career pathing directly to development through targeted learning plans . Instead of a generic recommendation to "develop leadership skills," you can point to a specific gap: "You need stakeholder management at Level 4 to move into the program manager role. You're currently assessed at Level 2. Here are the experiences and training that will close that gap." A skills gap analysis makes this concrete. It shows individuals exactly where they stand against the requirements of their target role, turning career development from a conversation into a dashboard. From individual paths to workforce strategy Skills-based career pathing isn't just an employee engagement tool — it's a workforce planning mechanism. When every employee has a visible, skills-defined career path, the organization gains a real-time map of where its talent is heading. You can see which roles have strong internal pipelines and which don't. You can use manager analytics to identify flight risks — employees whose skills have outgrown their current role but have no visible next step. You can forecast which skill gaps will emerge as people progress through their paths — feeding directly into succession planning and workforce strategy . According to Deloitte's 2024 Global Human Capital Trends report, 73% of organizations say that developing skills-based approaches to work is important, but only 10% have made significant progress. The gap isn't conceptual — everyone agrees skills-based career pathing is the right direction. The gap is operational. It lives in the difference between saying "we believe in career development" and having the data and systems to actually deliver it. Career clarity as a retention strategy People don't quit companies. They quit careers they can't see. When an employee looks ahead and finds only ambiguity — unclear expectations, invisible pathways, no connection between their development and their future — they start looking outside. Skills-based career pathing replaces that ambiguity with a navigable map. Not a promise that everyone will be promoted. A clear, honest picture of what growth looks like, what it requires, and where each person stands. That clarity is what keeps people engaged — not perks, not ping-pong tables, not annual bonuses. The ability to see a future and know what it takes to get there. FAQ What is skills-based career pathing? Skills-based career pathing defines career progression through specific skill requirements at each level rather than vague title hierarchies. Employees can see exactly which competencies they need to develop — and at what proficiency — to advance into their target roles, whether those roles are vertical promotions or lateral moves. How is career pathing different from succession planning? Career pathing is employee-facing — it helps individuals navigate their own growth. Succession planning is organization-facing — it ensures the company has qualified internal candidates for critical roles. Skills data powers both, but career pathing focuses on individual agency while succession planning focuses on organizational risk. What data do you need to start building career pathways? At minimum, you need a competency framework that defines skill requirements by role and level, plus current skills assessments for your employees. Manager and self-assessments against a consistent proficiency scale give you the baseline. From there, you can map gaps between current state and target roles. Can career pathing support lateral moves, not just promotions? Yes — and that's one of the strongest arguments for skills-based pathways. When paths are defined by skills rather than title sequences, lateral connections between roles become visible. An employee might discover they're already 70-80% qualified for a role in a different function, opening transitions that a traditional ladder would never surface. --- ## The Skills Maturity Model: Where Does Your Organization Stand? URL: https://skillsdb.com/blog/skills-maturity-model Every organization has skills data. The question is whether they know it, whether they can use it, and whether it drives any decisions that matter. Most HR leaders will tell you they want to be "data-driven" about talent. But when pressed on what skills their workforce actually has — not what job titles suggest, but verified, assessed competencies — the answer is usually a long pause followed by "we have some of that in spreadsheets." What Is a Skills Maturity Model? A skills maturity model is a framework for assessing how effectively an organization captures, manages, and applies workforce skills data to drive talent decisions. Organizations progress through distinct stages — from no formal skills tracking to fully integrated skills intelligence that informs hiring, development, succession planning, and workforce strategy. The model measures not just whether skills data exists, but whether it is structured, current, connected to business outcomes, and actionable at scale. Unlike technology maturity models that focus on tool adoption, a skills maturity model evaluates the organizational capability to translate skills data into strategic workforce decisions. Most organizations fall in the lower tiers, relying on informal knowledge or disconnected spreadsheets rather than systematic skills infrastructure. The Four Tiers of Skills Maturity After 18 years of working with organizations across manufacturing, professional services, government, and Fortune 500 enterprises, a clear pattern emerges. Organizations don't jump from chaos to intelligence overnight. They progress through predictable stages — and most are stuck earlier than they think. Tier 1: Flying Blind (Score: 0-25) No formal skills tracking. Managers rely on tribal knowledge and institutional memory to staff projects, plan training, and make promotion decisions. Skills data lives in people's heads, and when those people leave, the data walks out with them. This is more common than anyone admits. A 2024 Deloitte survey found that only 10% of organizations have mature practices for using skills data in workforce decisions ( Deloitte, "Skills-Based Organization," 2024 ). The remaining 90% are somewhere on the journey — and a significant portion haven't started. The tell: When a senior leader asks "who on our team can do X?" the answer requires a chain of emails and calls. Tier 2: Partial View (Score: 26-50) Some awareness exists. Maybe there's a spreadsheet-based skills matrix for one department, or the HRIS has a skills field that gets populated during annual reviews. Pockets of the organization have started tracking, but there is no enterprise-wide standard. The data is inconsistent, outdated within months, and siloed. The L&D team can't use it for training decisions because it doesn't connect to their systems. Workforce planning operates on job titles and headcount, not skills. The tell: Different departments define the same skill differently, and no one has reconciled the taxonomies. Tier 3: Getting Clearer (Score: 51-75) Processes exist. Competency frameworks have been defined for at least some roles. Assessments happen — maybe annually, maybe as part of a specific initiative. There's real data, and people are starting to use it. But it doesn't scale. The framework covers 40% of roles. Assessments are manual and time-consuming. Reports require someone to pull data from multiple sources and build a slide deck. The insights are valuable but episodic — a snapshot, not a stream. According to McKinsey's 2025 workforce research, 87% of organizations say they either have skills gaps now or expect them within the next five years ( McKinsey, "Mind the Skills Gap," 2025 ). Tier 3 organizations can feel those gaps. They just can't quantify them fast enough to act. The tell: Leadership gets a skills gap report once a quarter. It's already outdated by the time it's presented. Tier 4: Skills Intelligent (Score: 76-100) Skills data drives decisions across the organization. Frameworks are comprehensive, assessments are regular and lightweight, and the data flows into workforce planning, hiring, succession, and training allocation in real time. Managers can search for internal experts by skill using a skills library . Employees can see what skills they need for their next role and what development resources map to those gaps. HR can model the impact of attrition on skill coverage through gap analysis . L&D can allocate training budget to the gaps that matter most, not the loudest requests. This is where skills tracking becomes skills intelligence — the shift from recording what exists to predicting what's needed. This is the level where workforce strategy becomes data-driven rather than intuition-driven. The tell: When a new initiative requires a capability the org doesn't have, leadership can quantify the gap and decide between build, buy, or borrow within days, not months. Why Most Organizations Get Stuck at Tier 2 The gap between Tier 2 and Tier 3 is the hardest to cross — and it's not a technology problem. It's an organizational one. Building competency frameworks requires cross-functional alignment. Running proficiency assessments requires manager buy-in and employee trust. Maintaining the data requires a system that makes updates lightweight, not a quarterly spreadsheet exercise that everyone dreads. Organizations get stuck because they try to boil the ocean. They attempt to define every skill for every role before launching anything. The better approach: start with one job family, define its core competencies, run assessments, prove the value, then expand. Score your organization's maturity to see exactly where you stand and what the next step looks like. From Measurement to Intelligence The maturity model isn't a judgment. It's a diagnostic. Every organization starts at Tier 1 — including the ones that have reached Tier 4. What separates the organizations that progress from the ones that stay stuck is a simple decision: treat skills as infrastructure, not as a project. A project has a start and end date. Infrastructure is something you build, maintain, and build on top of. The organizations that reach Tier 4 didn't get there by buying better software. They got there by making skills data a first-class citizen in their decision-making architecture — as fundamental as financial data or customer data. The tools matter, but the commitment matters more. Where you are on this model determines what you should do next. Not what you should buy — what you should build. FAQ What is a skills maturity model? A skills maturity model is a framework that assesses how effectively an organization captures, manages, and uses workforce skills data. It typically defines four progression stages, from no formal tracking to fully integrated skills intelligence that drives hiring, development, and workforce planning decisions. How do I assess my organization's skills maturity level? Start by evaluating three dimensions: data quality (do you have structured, current skills data?), process maturity (are assessments regular and standardized?), and decision integration (does skills data inform workforce planning, hiring, and training?). A structured self-assessment like the Skills Gap Calculator can score your current state and identify gaps. What is the difference between skills tracking and skills intelligence? Skills tracking records what skills exist in your workforce — it's a database. Skills intelligence uses that data to identify gaps, predict future needs, align training to strategy, and inform decisions across hiring, succession, and workforce planning. Tracking is a prerequisite. Intelligence is the goal. How long does it take to move from Tier 1 to Tier 4? Most organizations take 12-24 months to move from Tier 1 to Tier 3, depending on organizational size and commitment. The jump to Tier 4 requires sustained investment in data quality, manager adoption, and process integration. Start with one job family and expand — trying to cover the full organization at once is the most common reason initiatives stall. --- ## Skills Matrix: The Complete Guide (+ Free Template) URL: https://skillsdb.com/blog/skills-matrix-complete-guide A skills matrix is a grid that maps people to skills and shows each person's proficiency at every intersection. Rows are people, columns are skills, cells are ratings. It is the simplest useful artifact in workforce planning, and it answers the question every manager eventually asks in a hurry: who on this team can do this, right now, and how well? Quick reference: Skills Matrix — the short version of this post, with the one table that matters. Every organization tracks skills somewhere. The question is whether that somewhere is a spreadsheet buried in a manager's drive, a tab inside an HRIS that nobody updates, or a system that drives decisions. For most teams it is the spreadsheet, and for most teams the spreadsheet is already out of date. This guide covers what a skills matrix is, how it differs from its cousins, how to build one in six steps, what it looks like across functions, what the free template contains, and the point at which a grid stops being enough. What Is a Skills Matrix? A skills matrix is a visual framework that maps employees against the skills and competencies their roles require, rating proficiency for each. Team members run down one axis, skills across the other, and each cell holds a proficiency score, most commonly on a 1 to 5 scale. Organizations use it to find capability gaps, set training priorities, staff projects, support succession, and prove competency coverage to auditors. The format ranges from a spreadsheet for one team to a platform that maintains a live, organization-wide record. The purpose is the same at any scale: make skills visible so leaders can act on them. Unlike a job description, which describes what a role requires in theory, a skills matrix records what your people can actually do today. Unlike a competency framework, which sets the target, the matrix shows the current state. The gap between the two is where every development, hiring, and staffing decision lives. Why Teams Build One You do not need a skills matrix for everything. You need one when: You are staffing a project and need to know who has the capability, not who is loudest about it. Someone resigns and you need to know what expertise just walked out the door. You are building a training plan and want to fund the gaps that matter, not the requests that are easiest to approve. An audit is coming and you need documented evidence of who is qualified for which tasks. The team is growing and you have to decide whether to hire, develop, or restructure. If you have ever posted "does anyone here know how to do X?" in a team channel, you needed a skills matrix. Skills Matrix vs. Training Matrix vs. Competency Matrix Three grids, three different questions. Teams conflate them and end up with one spreadsheet trying to answer all three badly. Skills matrix Training matrix Competency matrix Question it answers Who can do what, and how well? Who has completed which training, and when does it expire? Who meets the role's required competency levels? Cells contain Proficiency ratings Completion status and dates Required vs. actual level per competency Source of truth Assessment Training records, certificates Competency framework plus assessment Decays when Skills go unpracticed Certifications expire Roles change or proficiency lapses Primary users Managers, resource planners Training and compliance leads HR, L&D, succession planning A training matrix tells you someone attended the forklift course in March. A skills matrix tells you whether they can drive the forklift. In regulated environments you need both, because auditors ask for the training record and then ask you to prove competence. The training side is covered in How to Build a Training Matrix . A competency matrix is a skills matrix organized around role-level competencies rather than discrete skills; most mature frameworks combine the two, with technical skills showing what someone can do and competencies showing how they do it. How to Build a Skills Matrix in 6 Steps Step 1: Scope one team One team or one department. Not the company. A first matrix should cover 15 to 25 people and 8 to 15 skills. That is small enough to finish in weeks and large enough to produce a decision on the first pass. Organizations that start with the whole company produce a beautiful empty grid. Step 2: Choose the skills that differentiate performance Do not list every skill the team uses. List the ones that separate strong performers from average ones and the ones the business cannot operate without. A software team tracks frontend, backend, system design, DevOps, testing, security, technical documentation, and mentorship. A maintenance crew tracks electrical troubleshooting, PLC programming, hydraulics, rotating equipment, lockout procedures, and vendor certifications. Source the list from three places: your competency framework if you have one, manager input on what distinguishes top performers, and project post-mortems on what skill was missing when things went wrong. Write skills in your organization's own language. Imported taxonomies look impressive in a demo and wither once real managers have to rate real people against them. Step 3: Define the proficiency scale The matrix works only when a "3" means the same thing to everyone reading it. Use a scale with described levels: Foundational. Needs guidance. Can assist but not lead. Developing. Performs independently in routine situations. Proficient. Handles complex situations. Reliable performer. Advanced. Expert. Coaches others. Handles ambiguity. Mastery. Sets the standard. Recognized authority. Fewer than four levels loses the difference between "can help" and "can lead." More than seven creates false precision. Write one or two sentences per level per skill where the stakes are high; a level 3 in hydraulics should be described in hydraulics terms. Step 4: Run dual assessments Manager-only ratings miss blind spots. Self-ratings inflate. Run both, independently, and treat the delta as the coaching conversation. Ten skills take about fifteen minutes per person to self-rate and about the same for a manager per direct report. A few hours of total effort produces data that informs months of decisions. Step 5: Read the patterns Once the grid is filled, four patterns show up immediately: Single points of failure. One person rated 3 or higher on a skill the team depends on. If they leave, the capability leaves. Team-wide gaps. Nobody above a 2 on a skill the roadmap needs. That is a hire-or-train signal. Hidden strengths. Someone high on a skill the team does not use. That is a staffing opportunity, possibly for another team. Development priorities. The aggregate gap between current and required level across the team shows exactly where training money moves the needle. A skill gaps calculator does this arithmetic for you and ranks the exposure. Step 6: Connect it to decisions A matrix that does not drive a decision is decoration. Wire the findings into things that already happen: the training plan funds the largest gaps, the hiring plan covers the structural ones, project staffing pulls from the grid, and succession planning uses the advanced and mastery cells to find who is ready. Managers keep a matrix current when the matrix is where their decisions come from. They abandon it when it is a compliance chore. Skills Matrix Examples The shape is identical across functions. The columns change. IT and infrastructure. Skills: network configuration, virtualization, identity and access, backup and recovery, incident response, scripting, cloud platforms. The classic single-point-of-failure matrix; the one person who knows the legacy system is always a 5 in a column of 1s. Project management. Skills: scope control, scheduling, risk management, budget tracking, stakeholder communication, vendor management, methodology fluency. A project management skills matrix is often the first one a PMO builds because it directly feeds staffing. Manufacturing line. Skills by station: press setup, weld cell, final assembly, inspection, forklift, lockout procedures. Supervisors use it at shift start to confirm every station has a qualified operator and to plan cross-training so no station depends on one person. Data center operations. Skills: electrical switching, cooling systems, fire suppression, emergency operating procedures, vendor certifications, ticketing. Certification currency matters as much as proficiency here, so the matrix usually sits next to the training matrix. Healthcare unit. Skills: medication administration, IV therapy, patient handoff, specific equipment, code response. Charge nurses use it for assignments; educators use it to plan competency validation days. A small manufacturing example, with the required level for the station in the header: Operator Press setup (req 3) Weld cell (req 3) Final assembly (req 2) Inspection (req 3) Alvarez 4 2 3 3 Chen 3 4 2 1 Okafor 1 3 4 4 Patel 2 1 3 2 Read it and the decisions write themselves. Chen is the only weld cell operator at 4, and Alvarez needs to get to 3 before Chen's next vacation. Nobody but Okafor is qualified to inspect. Patel needs a development plan or the line has two stations exposed. That is a Tuesday's worth of decisions from sixteen cells. Skills Matrix Template The free skills matrix template is a Google Sheets workbook you can copy and use in Excel. It contains: A proficiency scale tab with the five levels above and space to write skill-specific descriptors. A team matrix tab with people as rows, skills as columns, and a required-level row for the role. A gap analysis tab that calculates each person's gap against the required level and totals exposure per skill. A dashboard tab that summarizes team capability, single points of failure, and the largest gaps. How to use it: copy it, rename the skill columns in your own language, set required levels per skill, have each person self-rate, have the manager rate independently, and review the deltas together before you trust the numbers. Run it quarterly. Trigger an update when someone joins, leaves, changes role, or completes training that changes a rating. An employee skills matrix built this way is also the best starting point for a competency matrix later. The people, the skills, and the scale carry forward; you add the role-level competency layer on top rather than starting over. When the Spreadsheet Stops Working A spreadsheet is the right tool for one team under roughly 50 people with stable skill requirements. It stops working at predictable points: Multiple teams with overlapping skills. Leadership wants one view. You have nine spreadsheets with nine versions of the scale. Multiple sites. A "3" in Ohio is not a "3" in Monterrey, and nobody can reconcile them. Audits. The auditor wants evidence behind the rating and a date on it. The spreadsheet has a number and a color. Decay. Skills go stale and certifications expire silently. Nothing in the grid knows that the level 4 was assessed two years ago. Connection to action. Gaps identified in the sheet have to be re-typed into the training system, the staffing tool, and the succession plan. The pattern is the same everywhere: the spreadsheet holds the data fine; it is the workflow around assessment, currency, evidence, and reporting that breaks. Skill requirements themselves are moving underneath the grid. LinkedIn's Workplace Learning research found that the skills required for jobs had changed about 25% since 2015, so a matrix frozen from last year is describing a job that no longer exists. Skills Matrix Software At the point where the spreadsheet breaks, the matrix needs to become a system of record: assessments that write dated, evidenced ratings; a scale that means the same thing across sites; currency tracking so lapsed skills surface on their own; and gap data that flows straight into learning plans, staffing, and succession without being retyped. That is what skills matrix software is for, and it is the transition SkillsDB was built around. The skills matrix in SkillsDB is a live view over assessed skills and proficiency, filterable by team, site, role, and required level, with the evidence behind every cell one click away. The Spreadsheet Isn't the Problem. The System Is. The real issue with skills tracking was never the format. It was the isolation. A spreadsheet can hold skill data. What it cannot do is keep that data current, connect it to training investments, surface it during staffing, or aggregate it for the workforce planning meeting. Skills data becomes skills intelligence when it flows: from individual assessment to team gap analysis to organizational planning and back. The matrix is the starting point. What you build around it determines whether it gathers dust or drives decisions. Start with the template. Move to a platform when complexity demands it. Never stop measuring. FAQ What is a skills matrix? A skills matrix is a grid that maps employees to skills and records each person's proficiency level at every intersection. It gives a team a current snapshot of capability, exposes gaps and single points of failure, and feeds training, hiring, staffing, and succession decisions with evidence instead of impressions. How do I create a skills matrix from scratch? Scope one team of 15 to 25 people, choose 8 to 15 skills that differentiate performance, define a five-level proficiency scale with written descriptors, have each person self-rate and each manager rate independently, then analyze the grid for gaps and concentration risks. Connect the results to the training plan and staffing decisions so the matrix stays in use. What proficiency scale should a skills matrix use? A five-level scale is the most practical: foundational, developing, proficient, advanced, and mastery, each with a short behavioral description. Fewer than four levels cannot distinguish someone who can help from someone who can lead, and more than seven creates precision nobody can apply consistently. What is the difference between a skills matrix and a training matrix? A training matrix records which courses and certifications each person has completed and when they expire. A skills matrix records how well each person can actually perform a skill, based on assessment. Regulated organizations need both, because auditors ask for training records and then ask for proof of competence. Can I use Excel or Google Sheets for a skills matrix? Yes, and for a single team under about 50 people you should. The free template works in either. Spreadsheets break when multiple teams or sites need one view, when auditors want dated evidence behind ratings, when skills and certifications decay unnoticed, and when gap data has to be retyped into other systems. How often should a skills matrix be updated? Quarterly is the right cadence for most teams, with event-triggered updates when someone joins, leaves, changes role, or completes training that changes a rating. Annual updates are too infrequent to reflect how fast skill requirements change, and monthly cycles create assessment fatigue. --- ## How to Measure Your Organization's Skills Gap (and Why Most Companies Can't) URL: https://skillsdb.com/blog/how-to-measure-skills-gaps Ask a VP of L&D which teams have the biggest skills gaps in their organization. Most can't answer with data. They'll point to anecdotal feedback, engagement survey results, or the fact that a particular team keeps missing deadlines. Some will reference training completion rates — which measure effort, not capability. This is the core problem with skills gap measurement: most organizations have built extensive systems for tracking what training people have completed and almost no systems for measuring what they can actually do. What Is a Skills Gap Assessment? A skills gap assessment is a structured process for measuring the difference between the skills an organization needs and the skills its workforce currently has, quantified at the individual, team, and organizational level. It involves defining required competencies for each role, evaluating current proficiency through multi-rater assessments (typically manager and self-assessment paired), and calculating the delta between required and actual skill levels. Effective skills gap assessments produce actionable data: which teams have the largest capability shortfalls, which skills represent the greatest organizational risk, and where training investment will generate the highest return. The output drives workforce planning, targeted development programs, and strategic hiring decisions. Without a structured assessment, organizations default to assumptions — and assumptions scale poorly. Why Can't Most Organizations Measure Their Skills Gaps? The barrier isn't willingness. It's infrastructure. No shared language for skills. McKinsey's 2024 report on workforce transformation found that 69% of organizations have increased their skill-building efforts since 2020, yet most lack a standardized framework for defining what skills they need. When the engineering team defines "data analysis" differently than the marketing team, you can't compare gaps across the organization. Assessment data is fragmented. Performance reviews capture some competency data. Training platforms track course completions. Certification systems hold credentials. But these systems rarely talk to each other — and none of them answer the question "what can this person actually do right now?" No baseline to measure against. A gap requires two numbers: where you are and where you need to be. Most organizations have never defined proficiency benchmarks for their roles. Without a target state, there's nothing to measure a gap against. How to Measure Skills Gaps: A Practical Framework 1. Define your competency framework first Start with job families — clusters of similar roles that share core competencies. For each job family, identify 8-12 core competencies and define what proficiency looks like at each level (typically a 0-5 scale). This framework is the foundation everything else builds on. The critical mistake here: adopting a generic, off-the-shelf taxonomy. Pre-built skill frameworks look comprehensive in a vendor demo, but they fail in practice because no two organizations define competency the same way. Your framework needs to use your language, mapped to your roles. 2. Run paired assessments Self-assessments alone inflate scores — the Dunning-Kruger effect is real and well-documented. Manager-only assessments miss capabilities that don't surface in day-to-day oversight. The most accurate approach pairs both: employees rate their own proficiency, managers rate independently, and the gap between those two ratings becomes a data point in itself. Run these by team, not all at once. A phased rollout across job families prevents assessment fatigue and lets you refine the process before scaling. 3. Calculate gap scores at three levels Individual: Where each person falls short of the proficiency benchmark for their role. This drives personal development plans. Team: Aggregate individual gaps to see which capabilities the team lacks collectively. This informs training investment and hiring priorities. Organization: Roll team-level data up to identify systemic gaps — skills the entire organization is underweight in. This is the data that belongs in the CHRO's workforce planning conversation. A skill gaps calculator can help you model these numbers and understand where your biggest exposures sit before running a full assessment cycle. 4. Prioritize by business impact, not gap size Not every gap matters equally. A 2-point gap in a revenue-critical skill matters more than a 4-point gap in a nice-to-have competency. Prioritization requires mapping skills to business outcomes: which capabilities directly affect revenue, customer satisfaction, regulatory compliance, or strategic initiatives? PwC's 2024 Global Workforce Hopes and Fears Survey found that 26% of CEOs believe skills shortages will threaten their company's ability to generate revenue over the next ten years. The skills gaps that connect to those revenue threats should be first in line for development investment. 5. Connect measurement to action Gap data without a response plan is just an audit. Every significant gap should map to one of four actions: Train: Develop the skill internally through targeted learning Mentor: Pair with an internal expert for skill transfer Stretch: Assign projects that build the missing capability Hire: Recruit externally when internal development timelines don't match business urgency The measurement process isn't complete until the gap data flows into development plans, staffing decisions, and training budgets. How Often Should You Measure Skills Gaps? Quarterly assessment cycles work for most organizations. Annual assessments are too infrequent — Gartner's 2024 research found that 58% of the workforce needs new skills to do their jobs successfully, and that number is growing. The skills landscape shifts faster than an annual review can capture. Between formal cycles, keep data current with event-triggered updates: certifications earned, training completed, project milestones hit. The Measurement Problem Is Really a Systems Problem Most organizations don't fail at skills gap measurement because they lack smart people or good intentions. They fail because their workforce data lives in disconnected systems that were never designed to answer the question "what can our people do?" Training platforms know what courses were completed. HRIS platforms know job titles and reporting structures. Performance management tools capture subjective manager ratings. None of them function as a system of record for actual skill proficiency. Solving the measurement problem means building — or adopting — a single place where skills data lives, stays current, and connects to the decisions that matter: who to train, who to hire, who to promote, and where the organization is most exposed. That's not a skills tab inside an existing system. It's a purpose-built layer of workforce intelligence. The organizations that get this right don't just measure gaps once. They build a continuous feedback loop — assess, develop, reassess — that turns skills data from a snapshot into a living system. Start by scoring where you stand today , and build from there. FAQ What's the difference between a skills gap analysis and a training needs assessment? A training needs assessment identifies what training to deliver. A skills gap analysis identifies what capabilities are missing and how severe the shortfall is — training is one possible response, but so is mentoring, stretch assignments, or strategic hiring. The gap analysis is the diagnostic step; training needs assessment is one part of the treatment plan. How do you measure skills gaps without a competency framework? You can't — at least not meaningfully. Without defined competencies and proficiency benchmarks, there's no "target state" to measure a gap against. Building a competency framework (even a lightweight one covering core skills per job family) is the necessary first step. Start with one team, define 8-12 core competencies, set proficiency levels, and expand from there. What data sources feed a skills gap assessment? The most reliable primary source is structured multi-rater assessment (self + manager). Supporting data includes certification records, training completion history, project performance data, and — where available — skills inference from tools and platforms employees use daily. No single source is sufficient; the accuracy improves as you layer sources. How do you quantify the cost of a skills gap? Map critical skills gaps to business outcomes: delayed projects, missed revenue targets, compliance risk, or increased external contractor spend. PwC's 2024 survey data shows that organizations with significant skills shortages report lower revenue confidence over 10-year horizons. The most direct calculation: cost of external hiring or contracting to fill a gap versus cost of internal development to close it. --- ## Competency Management: From Frameworks to Measurable Growth URL: https://skillsdb.com/blog/competency-management-frameworks-to-measurable-growth The competency management market reached $103 billion in 2023 and is projected to hit $154 billion by 2030, according to Grand View Research. That kind of growth suggests organizations are investing heavily in defining and developing workforce capabilities. But spending doesn't equal adoption. Most competency frameworks end up as beautifully formatted documents that nobody uses after the first quarter. Competency management is the practice of defining, assessing, and developing the skills and behaviors an organization needs to execute its strategy — connecting individual capability to business outcomes through structured frameworks, regular assessment, and targeted development. When done well, it transforms how organizations hire, promote, and develop people. When done poorly, it becomes shelfware. Why Do Most Competency Frameworks Fail? The pattern is predictable. A consulting firm spends three months building a comprehensive competency framework. It arrives as a polished PDF with dozens of competencies, behavioral indicators, and proficiency levels. Leadership signs off. HR sends an announcement email. And then nothing happens. The framework fails because it was built in a vacuum. The language doesn't match how managers actually describe performance. The competencies are generic enough to apply to any company, which means they feel specific to none. And there's no mechanism for assessment, tracking, or action — just a document. According to SHRM's 2023 research on talent management practices, fewer than 30% of organizations with competency models actively use them for development decisions. The rest have frameworks that exist on paper but never influence how people grow. The taxonomy trap Pre-built competency taxonomies are the biggest offender. They look impressive in vendor demos — thousands of competencies, neatly organized, ready to deploy. But no two organizations define competency the same way. A "project management" competency at a manufacturing firm means something fundamentally different than at a consulting firm. The behavioral indicators, the proficiency expectations, the context — all different. Real adoption requires frameworks built in the customer's own language, mapped to their roles and culture. Rigid taxonomies become shelfware because they feel imposed rather than owned. The organizations that get competency management right are the ones that invest in defining competencies that reflect how their people actually work. How to build a competency framework that sticks Start with job families, not individual roles. Group roles that share core capability requirements, and define competencies at that level first. This reduces complexity while maintaining relevance. Define competencies in plain language. If a manager can't explain a competency to a team member in a one-on-one conversation, the definition is too abstract. Use language your people already use. Borrow from performance reviews, project retrospectives, and job postings — that's where the real vocabulary lives. Limit the scope. Five to eight core competencies per role family is plenty. The urge to be comprehensive is the enemy of adoption. Every competency you add increases the cognitive load on managers and employees, which decreases the likelihood anyone will engage with the framework. Build in assessment from the start. A competency framework without a measurement mechanism is a wishlist. Manager and self-assessments against defined proficiency levels — using a consistent scale like 0 to 5 — give you actual data. That data turns a static document into a living system. You can use a competency matrix to visualize where gaps exist across teams and prioritize development investment. Connect competencies to outcomes. Every competency should link to something tangible: a career pathway, a promotion criterion, a project staffing requirement, or a training recommendation. If a competency exists in the framework but doesn't connect to any decision, cut it. From framework to system The difference between competency management that works and competency management that becomes shelfware is whether the framework lives in a system or in a document. Spreadsheets can get you started — and many organizations run their first competency matrix in a spreadsheet — but they break down at scale. You can't run assessments, track progress over time, or surface gap patterns across 300 people in a spreadsheet. A purpose-built competency management platform turns the framework into something managers and employees interact with regularly. Assessments generate scorecards. Scorecards surface gaps. Gaps connect to development recommendations. That cycle — define, assess, develop, reassess — is what makes competency management a growth engine rather than an HR project. The real measure of competency management The test isn't whether you have a framework. It's whether that framework changes how people develop. If a new hire can look at their role's competencies, understand what's expected, see where they stand today, and identify a clear path to growth — your competency management is working. If the framework sits in a shared drive and surfaces once a year during reviews, it isn't. Organizations that treat competency management as infrastructure — not as a project — build something durable. The framework becomes the connective tissue between hiring, development, succession, and workforce planning. That's the difference between a document and a system. FAQ What is competency management? Competency management is the systematic process of defining the skills, knowledge, and behaviors required for each role in an organization, then assessing employees against those standards and developing targeted plans to close gaps. It connects individual capability to business strategy through structured frameworks and regular assessment cycles. How is a competency framework different from a skills matrix? A competency framework defines the expected proficiency levels for each role or job family — it's the standard. A skills matrix maps where individuals or teams currently stand against those standards. The framework sets the target; the matrix shows the gap. Both are necessary for effective competency management. Why do pre-built competency taxonomies often fail? Pre-built taxonomies use generic language that rarely matches how a specific organization defines competency. A "leadership" competency at a hospital means something different than at a software company. Organizations that build frameworks in their own language — reflecting their roles, culture, and strategy — see significantly higher adoption rates. How many competencies should a role have? Five to eight core competencies per role family is the practical limit. Beyond that, the framework becomes too complex for managers and employees to engage with meaningfully. Focus on the competencies that most directly influence performance and career progression in your organization. --- ## Skills-Based Succession Planning: Move From Gut Feel to Data URL: https://skillsdb.com/blog/skills-based-succession-planning Only 21% of organizations have a formal succession plan, according to SHRM's 2024 Talent Trends report. That means four out of five companies are one departure away from a leadership vacuum. And of the 21% that do have a plan, most are built on the same shaky foundation: manager opinions about who's "ready." Succession planning should be one of the most data-driven processes in talent management. Instead, it's one of the most subjective. The VP says their director is "ready for the next step." The CHRO has a gut feeling about two high-potentials. The CEO remembers someone who impressed them in a meeting last quarter. These are the inputs to most succession decisions. Not skills data. Not assessed competencies . Not measured readiness. The result is predictable. CIPD's 2024 Resourcing and Talent Planning Survey found that 54% of organizations that had a succession event in the prior year said the transition was "somewhat" or "significantly" disruptive. Succession planning that relies on gut feel produces succession outcomes that feel like scrambling. What Is Skills-Based Succession Planning? Skills-based succession planning is the practice of identifying and developing future leaders by mapping critical roles to required competencies, assessing internal candidates against those competency benchmarks, and building targeted development plans to close readiness gaps. Unlike traditional succession planning, which relies heavily on manager nominations and subjective assessments of "potential," skills-based succession planning uses quantified skill data to evaluate bench strength, identify development priorities, and make promotion decisions based on evidence rather than opinion. It connects succession directly to the organization's competency framework — ensuring that the criteria for readiness are transparent, measurable, and consistent across the organization. Why Traditional Succession Planning Fails The failure modes are well-documented and remarkably consistent across industries and company sizes. The nomination problem In most organizations, succession candidates are nominated by their current managers. This creates three biases. First, visibility bias: managers nominate people they see regularly, disadvantaging remote employees, cross-functional contributors, and quiet high-performers. Second, similarity bias: managers tend to nominate people who remind them of themselves. Third, recency bias: the person who led last quarter's visible project gets nominated over the person who consistently delivers strong results without fanfare. A 2024 Harvard Business Review analysis of succession practices across 200 companies found that manager-nominated succession pools were 40% less diverse than pools identified through competency-based assessment — and 35% less likely to include candidates who succeeded in the target role within their first year. The "high-potential" trap Many succession programs label employees as "high-potential" based on performance in their current role. The problem: the skills that make someone excellent at their current job aren't the same skills their next role requires. An outstanding individual contributor doesn't automatically have the strategic thinking, stakeholder management, and team development skills that a leadership role demands. This is the Peter Principle in organizational form. Performance is being used as a proxy for readiness when the two measure fundamentally different things. The development gap Identifying successors without developing them is planning without execution. Deloitte's 2024 Global Human Capital Trends report found that while 86% of organizations consider succession planning important, only 14% believe they effectively develop identified successors for their target roles. The gap isn't intent — it's specificity. Telling someone they're "on the succession track" and sending them to a generic leadership program doesn't close the specific competency gaps between where they are and where they need to be. Development that doesn't target measured gaps is expensive guesswork. The black box problem In many organizations, succession plans exist in a confidential document that the CHRO maintains. Employees don't know they're being considered. Development isn't explicitly connected to succession readiness. And when a role opens, the "plan" often gets overridden by politics, urgency, or whoever the departing leader recommends. Succession planning that lives in a black box can't be systematic. It can't be measured. And it can't build organizational capability at scale. The Skills-Based Approach Skills-based succession planning replaces subjectivity with structure at every step. Step 1: Map critical roles to competency profiles Start with the roles that matter most. Not every position needs a formal succession plan — focus on roles where a vacancy would materially impact operations, strategy, or revenue. For each critical role, build a competency profile that defines the specific skills and proficiency levels required. This isn't a job description. It's a measurable benchmark. A VP of Engineering role might require: strategic planning (Level 5), technical architecture (Level 4), stakeholder management (Level 5), team development (Level 4), budget management (Level 3), and cross-functional leadership (Level 5). The competency profile becomes the objective standard against which all succession candidates are evaluated. Step 2: Assess bench strength With competency profiles defined, assess internal candidates against those benchmarks. This is where skills data replaces gut feel. Use proficiency assessments — both manager and self-assessment — to measure each candidate's current level on the competencies that matter. The dual assessment approach is critical. Manager-only assessments miss self-awareness. Self-assessments alone tend to inflate scores. The delta between the two becomes a development conversation. The output is a readiness score for each candidate: how close are they to the competency profile of the target role? Not "they seem ready" but "they meet the benchmark on 8 of 12 competencies and have gaps of 1-2 levels on 4 others." Step 3: Quantify the gaps For each succession candidate, the gap analysis produces a specific development prescription. Not "develop leadership skills" but "close a 2-level gap in strategic planning, a 1-level gap in stakeholder management, and a 2-level gap in budget management." This specificity is what makes development plans actionable. A 1-level gap might close through mentoring or a stretch assignment. A 2-level gap likely needs formal development plus coached practice. A 3+ level gap raises the question of whether the candidate is realistic for the role within the planning horizon. The gap analysis should show readiness at both the individual and organizational level. How deep is your bench for each critical role? How many candidates are within development range? Where are you most exposed? Step 4: Build targeted development plans Each identified gap should connect to a specific learning plan — not a generic leadership program, but a sequence of development activities designed to close measured gaps. The plan should specify: Which competency needs development Current proficiency level and target level Development activity (training, mentoring, stretch assignment, job rotation) Timeline and milestones How readiness will be reassessed This is where succession planning and talent development converge. The succession plan identifies who needs to develop which capabilities. The development plan makes it happen. Skills data connects the two. Step 5: Track readiness over time Succession readiness isn't a point-in-time assessment. It's a trajectory. Quarterly reassessments show whether development plans are working — whether candidates are actually closing gaps and moving toward readiness. Track two metrics for each critical role: Bench strength: How many candidates are within development range (defined as 1-2 levels below benchmark on no more than 3 competencies)? Organizations with strong succession planning maintain a bench depth of 2-3 viable candidates per critical role. Time to readiness: Based on current development velocity, how long until each candidate meets the competency benchmark? If your best candidate for a role is 24 months from readiness and the current incumbent is considering retirement, you have a gap that might need to be filled externally. What the Data Makes Possible Skills-based succession planning produces capabilities that opinion-based approaches can't match. Transparent criteria When succession decisions are based on competency profiles, the criteria are visible and consistent. Candidates know what the target role requires. They can see their own assessment data. They understand which gaps they need to close. This transparency improves engagement — people are more likely to invest in development when they can see the path and trust the process. Earlier identification Manager nominations tend to focus on people who are already close to ready. Skills data can identify candidates earlier in their career who show high aptitude across the relevant competencies but haven't been nominated because they're not yet visible at senior levels. Searching the organization's skills data for people who already meet 70%+ of a critical role's competency profile — regardless of their current title or department — often surfaces candidates that subjective processes miss. This is especially powerful for improving diversity in succession pipelines. Cross-functional mobility Traditional succession planning looks within the function. The next VP of Sales comes from the sales organization. The next VP of Engineering comes from engineering. Skills data can reveal that a director in Product has 90% of the competencies required for a VP of Engineering role — or that a high-performing operations leader has the strategic thinking and stakeholder management skills that would make them an effective CHRO candidate. The use case page on succession planning explores these cross-functional scenarios in more detail. Board-ready reporting When succession data is quantified, it can be reported at the board level with confidence. "We have bench strength of 2.4 candidates per critical role, with an average time-to-readiness of 14 months. Our highest-risk role is VP of Data Science, where we have one candidate at 18 months from readiness and recommend external hiring as a parallel track." That's a fundamentally different board conversation than "we feel good about our pipeline." Starting the Shift Moving from opinion-based to skills-based succession planning doesn't require replacing everything at once. Start with the five most critical roles in the organization — the ones where a vacancy would be most disruptive. Build competency profiles for those roles. Assess the top 2-3 internal candidates for each. Quantify the gaps. Build development plans for the most promising candidates. Reassess in 90 days. That pilot will produce two things: better succession data for those five roles, and a proof of concept that demonstrates the value of the approach to leadership. From there, expand to the next tier of critical roles and systematize the assessment process. Before you start, assess your organization's current skills gap visibility. The Skill Gap Calculator takes two minutes and tells you whether your skills infrastructure can support data-driven succession — or whether you need to build that foundation first. Succession planning is too important to leave to gut feel. The data exists to do it better. The organizations that use it will have an unfair advantage in leadership continuity, internal mobility, and workforce resilience. Those that don't will keep scrambling every time someone gives notice. FAQ What is skills-based succession planning? Skills-based succession planning identifies and develops future leaders by mapping critical roles to competency profiles, assessing internal candidates against those benchmarks, and building targeted development plans to close specific readiness gaps. It replaces subjective manager nominations with quantified skill data as the basis for succession decisions. Why does traditional succession planning fail? Traditional approaches rely on manager nominations (which introduce visibility, similarity, and recency bias), use current-role performance as a proxy for next-role readiness (the Peter Principle), and often identify successors without building specific development plans to close competency gaps. The result is succession plans that look good on paper but produce disruptive transitions. How do you assess succession readiness using skills data? Build a competency profile for the target role that specifies required skills and proficiency levels . Assess candidates using dual manager-self assessments against those benchmarks. The gap between current proficiency and the role benchmark produces a readiness score — specific enough to drive targeted development and measurable over time. How many succession candidates should each critical role have? Best practice is 2-3 viable candidates per critical role. "Viable" means within development range — no more than 1-2 proficiency levels below benchmark on no more than 3 competencies. Having fewer than 2 candidates per role represents concentration risk. Having more than 4 dilutes development investment. How often should succession readiness be reassessed? Quarterly reassessments balance accuracy with assessment fatigue. Between formal cycles, event-triggered updates — completed certifications, new project leadership, role changes — keep readiness data current. Annual succession reviews are too infrequent to track development progress or detect changes in bench strength. Can skills-based succession planning improve diversity? Yes. Subjective nomination processes tend to replicate existing leadership demographics. Skills-based assessment evaluates candidates against objective competency benchmarks regardless of visibility, department, or relationship with current leaders. Organizations that search the full skills database for competency matches — rather than relying on nominations — consistently surface more diverse candidate pools. --- ## Skills-Based Hiring: How to Hire for Skills, Not Resumes URL: https://skillsdb.com/blog/skills-based-hiring The resume has been the default hiring currency for over a century. A one-page summary of where someone worked, what degree they earned, and which job titles they held. It tells you almost nothing about what a person can actually do. Employers are starting to agree. According to TestGorilla's 2024 State of Skills-Based Hiring report, 81% of employers now use some form of skills-based hiring — up from 57% in 2022. And 90% of those employers say they make better hires as a result ( TestGorilla, 2024 ). What Is Skills-Based Hiring? Skills-based hiring is a talent acquisition approach that evaluates candidates primarily on demonstrated abilities and competencies rather than degrees, job titles, or years of experience. Organizations using this method define the specific skills required for a role, then assess candidates against those requirements through structured evaluations, work samples, or skills assessments. The approach widens the talent pool by removing artificial barriers — like requiring a four-year degree for roles where the degree has no correlation to performance. It also improves quality of hire by measuring what candidates can do rather than where they have been. Companies including Google, IBM, and Accenture have removed degree requirements from significant portions of their job postings, signaling a broader shift toward skills as the primary hiring signal. Why Are Resumes Still the Default? Inertia, mostly. Resumes are easy to collect, easy to filter, and easy to hand to a hiring manager who doesn't have time to think harder. ATS systems are built around keyword matching against resumes. Recruiting workflows are structured around screening credentials first, evaluating skills later — if at all. The problem is that this workflow optimizes for speed of screening, not quality of outcome. Harvard Business School and Accenture found in a 2022 study that degree requirements screened out over 60% of workers who already had the skills to perform the role ( Harvard Business School, "Hidden Workers" ). The resume acts as a filter that removes qualified candidates before anyone assesses whether they can do the job. What Does Skills-First Hiring Actually Require? Posting "no degree required" on a job listing and changing nothing else is not skills-based hiring. It's a press release disguised as a process change. Real skills-first hiring requires three things: A clear skills framework for every role. You need to define what skills the role actually requires — not a wish list of 25 competencies, but the 5-8 that genuinely predict success. This means working with hiring managers to separate "nice to have" credentials from "must demonstrate" capabilities. A way to assess those skills before the interview. Structured skills assessments, work samples, or portfolio reviews that evaluate candidates against the defined framework. The assessment has to happen early in the process — not as a final check after three rounds of credential screening. Skills data that connects hiring to development. When a new hire's assessed skills feed directly into their development plan, you create a continuous loop. The gap between what they demonstrated in hiring and what the role requires at full performance becomes their onboarding roadmap. Score your organization's readiness for this shift to see where the gaps are. The Degree Requirement Is Falling — But Slowly The trend line is clear. Between 2014 and 2023, the share of U.S. job postings requiring a bachelor's degree dropped from 51% to 44%, according to the Burning Glass Institute's 2024 analysis of over 90 million job postings ( Burning Glass Institute, 2024 ). State governments are leading: over 20 U.S. states have removed degree requirements from public sector roles since 2022. But dropping the requirement without building the assessment infrastructure creates a new problem. Hiring managers default to what they know — resume scanning, gut feel, referral networks. Without a structured way to evaluate skills, removing the degree requirement just moves the bias from one filter to another. From Screening to Signal The organizations getting this right treat skills-based hiring as a systems change, not a policy change. They map roles to competency frameworks. They build assessment processes that generate real signal about candidate capability. They connect that signal to onboarding and development so the data compounds over time. This is where the shift from tracking skills to using skills intelligence matters. A platform that can define role requirements, assess candidates against those requirements, and then carry that skills data into the employee's development journey isn't just a hiring tool. It's the foundation for a workforce strategy that starts before day one. Skills-based hiring isn't a trend. It's the logical conclusion of a labor market that has been over-indexing on credentials and under-investing in capability for decades. The organizations that build the infrastructure to hire on skills — not just talk about it — will find better people, faster. And they'll keep them longer, because they can show every employee exactly what they need to grow. FAQ What is the difference between skills-based hiring and traditional hiring? Traditional hiring screens candidates primarily on resumes, degrees, and job titles. Skills-based hiring evaluates candidates on demonstrated competencies and abilities through structured assessments. The shift focuses on what a candidate can do rather than where they have been. Do companies that use skills-based hiring get better results? Yes. TestGorilla's 2024 report found that 90% of employers using skills-based hiring say they make better hires, and 91% reported reduced total cost-to-hire. Organizations also see wider, more diverse talent pools when degree requirements are removed. How do you implement skills-based hiring? Start by defining a clear competency framework for each role — the 5-8 skills that predict success. Build structured assessments into the early stages of your hiring process. Then connect hiring skills data to onboarding and development plans so the data compounds over each employee's tenure. Does skills-based hiring mean degrees don't matter? Not at all. Degrees still matter for roles where the credential is directly relevant — licensed professions, specialized research, regulated fields. Skills-based hiring means degrees stop being a universal filter applied to roles where they have no correlation to performance. --- ## Introducing SkillsDB Employee Surveys URL: https://skillsdb.com/blog/employee-surveys Listening. With Purpose. The story of surveys began nearly two centuries ago, on paper and punch cards. Over time, they evolved—from Likert scales and telephone polling to the first online employee engagement surveys in the 90s. But, the value at the end of most surveys never materialized. We’ve spent decades helping organizations map and grow what their people can do —their skills, competencies, and paths toward mastery. With today’s release, we’re introducing Employee Surveys : a simple, integrated way to collect employee data that feeds automatically into a continuous system-of-record for employee capabilities. Where most survey tools fall short We’ve all used general survey tools. They make it easy to get quick answers, but stop short of what comes next, leaving your valuable survey data stranded in spreadsheets. We’ve built something very different. With SkillsDB, your survey results create an open-ended, evolving window into employee interests, skills, training, capabilities, and experience—instantly searchable for workforce planning and talent development . You can now combine skill assessments, competency frameworks, resume data, and employee surveys into one unified view of your global workforce. From signal to action Most survey projects end with their results in a big spreadsheet. They measure engagement, eNPS, and satisfaction—and then leave the heavy lifting to you. SkillsDB’s survey experience is different by design. Because it’s built inside the SkillsDB ecosystem, every response lives where real growth happens: next to your skills matrices , learning plans, and competency frameworks . When employees tell you they need clearer goals or better access to training, those insights aren’t stranded in a spreadsheet—they’re tied directly to your system of record—SkillsDB. This transforms a pulse survey from a periodic check-in into a strategic lever. Search survey results alongside skills, certifications and training Launch targeted learning plans from recurring themes Track how sentiment evolves as training and coaching improve Every survey becomes a productive feedback loop. Why this matters Our mission is to make learning culture universal . To be the place where every skill, competency, job architecture and career path lives, creating a deep source of intelligence about your team. Adding surveys makes that system smarter, more human, and more complete. It brings the voice of the employee into the same ecosystem that drives their growth. In a world where talent, learning, and people operations are converging, SkillsDB Surveys unify employee feedback, learning data, and performance insights in one continuous motion—bridging HR, L&D, and operations with clarity and context. A logical extension of purpose By combining skills intelligence with real-time employee feedback, organizations can finally see the full spectrum of success: what people are capable of, how they’re feeling, and what they need to climb higher. That’s what this release represents—a natural next step toward making SkillsDB the mission control for employee success . What does this mean, in practice? A single place where companies can map skills, define competencies, curate learning, clarify job architecture, design career paths, and now, listen at scale through a modern employee engagement platform. Want to see the future of workforce strategy, resource planning, and L&D? Book a demo to learn more. FAQ What is the SkillsDB Employee Survey tool? It’s a fully integrated employee survey platform within SkillsDB that helps organizations measure engagement, sentiment, and culture—all connected to their existing skills and competency data. How is this different from other employee survey tools ? Most survey products collect data in isolation. SkillsDB connects every survey response, creating a full view of employee growth and experience. How does this help HR, L&D, and Operations teams? Surveys connect employee feedback to learning and development priorities. HR gets engagement insights, L&D identifies skill gaps, and operations sees where process improvements impact morale—all in one system of record. How can resource planners use SkillsDB Surveys? Unlike other survey tools, SkillsDB allows for collecting data about employee knowledge and experience continuously, and make it searchable across teams or your global workforce.. What types of surveys can I run? You can create engagement surveys, pulse surveys, onboarding or exit surveys, and even team-specific check-ins tied to roles, projects, or competencies. What is a pulse survey? A pulse survey is a short, frequent check-in that captures how employees are feeling in the moment—ideal for tracking progress or reactions to change between larger engagement surveys. What is eNPS and how does it fit into SkillsDB? Employee Net Promoter Score (eNPS) measures how likely team members are to recommend your organization as a great place to work. SkillsDB includes eNPS alongside qualitative questions for richer context and trend tracking. Why are employee engagement surveys important? They help leaders stay connected to their teams, identify barriers to performance, and act early on issues that affect productivity, retention, and morale. How often should we run employee surveys? Most organizations benefit from a quarterly cadence, using pulse surveys in between to stay responsive without overwhelming employees. Can we link survey results to skills or competencies? Yes. Results can be analyzed alongside skills data to understand how confidence, capability, and engagement align. This creates a clear connection between learning investment and employee sentiment. Who can access survey insights? HR, L&D, and operations leaders have full visibility, while managers receive scoped insights for their teams—empowering local action without compromising privacy. Does SkillsDB provide benchmarking or trend analysis? Yes. You can compare results across teams, departments, or time periods, and benchmark engagement metrics such as eNPS to identify where improvement is needed most. How can survey insights be turned into action? Every survey response links directly to actionable pathways—launching training programs, updating playbooks, or refining competencies—so improvements happen where they matter most. How do surveys contribute to a high-performance learning culture ? They close the loop between listening and development. Insights reveal where teams need support, which skills require reinforcement, and how employees experience growth over time. Is this tool useful for small teams or large enterprises? Both. Smaller teams benefit from quick, continuous feedback, while larger enterprises can analyze engagement across complex organizational structures with the same clarity. What metrics can we track beyond eNPS? SkillsDB supports tracking for engagement drivers such as recognition, career growth, leadership, communication, and alignment with company values. How do employee surveys connect to SkillsDB’s broader vision? Surveys are a natural extension of SkillsDB existing products to be the system of record for all things related to employee success—uniting skills, competencies, playbooks, learning, and feedback into one integrated experience. --- ## How to Upskill Your Workforce: Best Practices for the Future of Work URL: https://skillsdb.com/blog/upskilling-2025-future-of-work A Universal Imperative Upskilling is no longer optional; it is the defining strategy for organizations navigating today’s accelerated pace of change. Technical, compliance, and even interpersonal skills now decay faster than ever. The half-life of a skill is often measured in months, not years. Whether in a globally dispersed remote team or on the frontline of a factory floor, the need to continuously upgrade capabilities is truly universal. A Brief History of Upskilling The idea of retraining workers is centuries old, but the language is new. The Oxford English Dictionary cites the first recorded use of the verb upskill in the Daily Telegraph in 1983. Since then, “upskilling” has moved from jargon to boardroom mandate. From the Industrial Revolution to the Digital Age, every transformation in work has required learning new skills. Today’s difference? The scale and speed are unprecedented. Scale of the Modern Challenge The need today is staggering: McKinsey Global Institute projects that 375 million workers (14% of the global workforce) will require upskilling or reskilling by 2030. From the same report, more than 50% of workers report undergoing some form of upskilling or reskilling (up from 41% in 2023). The World Economic Forum’s Future of Jobs Report 2025 forecasts that 59% of employees will need new skills by 2030 . Every merger, software rollout, factory restructure and regulatory shift changes day-to-day work. The choice for organizations is clear: build skills from within or risk obsolescence. Upskilling vs. Reskilling These two concepts are often confused: Upskilling deepens existing skills. A frontline technician learning digital dashboards or a remote analyst mastering AI-driven reporting. Reskilling prepares workers for entirely new roles. A plant operator becoming a logistics coordinator or a customer service agent shifting to digital content support. Both are essential. Upskilling sustains current performance; reskilling secures long-term adaptability. Why Upskilling Matters Now For organizations : Productivity, retention, employee happiness, smoother adoption of new tools, compliance confidence, and resilience. For employees : Career clarity and advancement, relevance in the labor market, and confidence their employer invests in their growth. This is as true for remote and hybrid employees as it is for factory and frontline workers where safety and efficiency depend on continuous training. Best Practices for Workforce Upskilling To succeed, companies must move beyond ad-hoc training and rote team sessions to a continuous culture of learning. Key steps include: Conduct a skills gap analysis — Assess current vs. future workforce needs. Build employee development plans — Align business goals with personal career growth. Enable learning in the flow of work — Deliver microlearning and just-in-time support. Adopt blended learning approaches — Combine on-the-job training, mentorship, certifications, and adaptive tools. Leverage enabling technology — Use digital adoption platforms, in-app guides, and knowledge management systems. Measure impact — Track adoption, error reduction, retention, and productivity outcomes. SkillsDB Point of View Upskilling succeeds when organizations build a learning culture anchored in: Skills visibility — knowing what capabilities exist. Expert validation — ensuring skills are real and measurable. Strategic alignment — focusing on the skills that drive business outcomes. Without these, training is scattershot. With them, upskilling becomes the connective tissue of a resilient, high-performing workforce. Act Now to Build a Winning Team The word upskill may have entered the dictionary in 1983, but in 2025 it has become the defining strategy for thriving organizations. From globally dispersed remote teams to frontline operators, the companies that win will be those who invest continuously in their people. At SkillsDB, we help enterprises make upskilling real—transforming skill and competency data into an engine for learning culture, workforce planning, and growth. 👉 If you’re ready to build a culture of continuous upskilling, contact us today to see how SkillsDB can help your teams thrive. FAQs What is upskilling in the workplace? Upskilling in the workplace means providing employees with additional training and learning opportunities to expand their current skills, keep pace with evolving technology, and perform more effectively in their roles. What is the difference between upskilling and reskilling? Upskilling enhances existing skills for current roles, while reskilling prepares employees for entirely new roles. Both are essential for adapting to technological change and business transformation. Why is upskilling important in 2025? The World Economic Forum predicts 59% of employees will need new skills by 2030. As AI, automation, and hybrid work reshape industries, upskilling ensures employees remain relevant, adaptable, and engaged. What are examples of upskilling? Examples include training a factory worker to use digital dashboards, helping a marketing team master analytics tools, or enabling managers to build cross-cultural collaboration skills for global teams. How does upskilling impact employee retention? Employees who see their organization investing in their growth are more engaged and loyal. Research shows companies with strong learning cultures have higher retention and lower turnover. How can companies identify which skills to upskill? Start with a skills gap analysis: compare current workforce capabilities to future business needs. Tools like SkillsDB make this visible, aligning workforce planning with strategy. How does upskilling help frontline and factory workers? Upskilling ensures safety, productivity, and career advancement. For frontline staff, this might mean new compliance training, digital tool adoption, or cross-training to handle more complex tasks. How do remote and hybrid teams benefit from upskilling? Remote employees rely on digital fluency, collaboration tools, and adaptive workflows. Upskilling ensures they remain connected, productive, and aligned despite geographic dispersion. What role does AI play in upskilling? AI enables personalized learning, skills inference, and adaptive pathways. It can identify emerging skills, recommend targeted training, and even validate expertise in real time. What are the challenges of upskilling? Common challenges include lack of visibility into skills, limited time for training, resistance to change, and failure to connect upskilling to measurable business outcomes. How do you measure the ROI of upskilling programs? ROI can be measured through increased productivity, reduced errors, faster technology adoption, higher employee retention, and direct alignment with strategic goals. What industries need upskilling the most? All industries face pressure, but manufacturing, healthcare, logistics, financial services, consulting businesses, and tech-heavy fields experience especially rapid skill evolution. How often should employees be upskilled? At minimum, annually for fast-moving technologies and regulatory requirements. In practice, continuous microlearning and real-time skill validation are best. Is upskilling only for technical roles? No. Leadership, communication, compliance, and collaboration skills are equally critical. Soft skills and adaptive thinking are often what differentiate high-performing teams. --- ## Who Knows What? How to Find (and Prove) Expertise Inside Your Company URL: https://skillsdb.com/blog/who-knows-what-experts Every company has hidden experts—people with the knowledge to win proposals, guide projects, or mentor colleagues—but too often, they remain invisible. The real challenge isn’t a lack of expertise, it’s knowing who knows what and being able to prove it when it counts. The quiet tax of not knowing “who knows what” When teams can’t quickly find an internal expert, work slows down, proposals get weaker, and risk creeps into delivery. Multiple recent studies show the drag is real: Microsoft’s 2024 Work Trend Index found that 57% of people struggle to find the information they need at work and over half say they’re wasting time searching or recreating content . ( Microsoft research ) APQC’s survey data (~1,000 knowledge workers) shows employees spend ~2.8 hours every week just looking for or requesting needed information , with more time lost to communication churn and unnecessary meetings—collectively “one quarter of a knowledge worker’s time” lost to productivity drains. Vendor studies corroborate the magnitude: in large U.S. enterprises, inefficient knowledge sharing has been estimated to cost ~$47M/year in lost productivity—driven by hours waiting on colleagues or recreating existing know-how. Back-of-the-envelope ROI: If your 1,000 knowledge workers each lose even 2.8 hours/week, that’s 2,800 hours/week. At a conservative $60/hour loaded cost, that’s $168,000/week → $8.7M/year—before considering proposal win-rates, cycle-time, or rework. [Change the employee count and their average loaded cost to compute for your company or team.] From corporate “yellow pages” to AI expert-finders Long before enterprise search, global firms built “corporate yellow pages”—internal directories that mapped who knew what across far-flung teams. The knowledge-management literature describes these as expertise locator systems: searchable staff lists that point you to the human with the tacit know-how you need. Real-world cases followed: Siemens ShareNet connected sales and marketing to experts and best practices worldwide; Xerox Eureka captured field technicians’ fixes so peers could find and reuse them—both classic examples of expertise discovery improving time-to-resolution. In high-reliability settings, expert-finding isn’t optional—it’s mission critical. NASA has formalized “knowledge capture and transfer” to mitigate knowledge loss during retirements and transitions , and runs agency-wide lessons-learned systems precisely so teams can find the right know-how (and the right people) when it matters. As we discussed recently , on the shop floor, the skills matrix made expertise visible at a glance so leaders could staff, cross-train, and maintain quality. That same visual pattern now scales to knowledge work across large global enterprises. What the research says about expert visibility and performance In organizational science, teams with a strong Transactive Memory System (TMS)—i.e., a shared “map” of who knows what—perform better, coordinate faster, and adapt more effectively. Recent peer-reviewed work (2024+) continues to show TMS as a mediator of job performance and a driver of team outcomes: when people can find the right expert, they solve problems faster and with higher quality. ( Read more here ) Meanwhile, the everyday drag remains substantial: multiple large-scale workplace reports put time spent searching at ~3 hours per day on average—a huge productivity sink that compounds when expertise is siloed. Compliance: why “provable expertise” matters Beyond speed, many regulated frameworks expect demonstrable competence: ISO 9001:2015 (Clause 7.2) requires organizations to retain documented evidence of competence—which, practically, means you must know who your experts are and show proof. ISO 27001 (Clause 7.2) requires ensuring and evidencing competence for roles affecting the ISMS. SOC 2 doesn’t prescribe competence the way ISO does, but auditors evaluate Communication & Information (CC2.x) and expect role-appropriate training evidence and clear responsibilities—both helped by expert mapping and sign-off trails. If you can prove an employee’s critical skill with an expert sign-off , that’s gold for audits, customer due diligence, and internal risk management. But when put to practice, all of this still matters outside of compliance frameworks for workforce planning and workforce strategy. A practical playbook to surface and prove expertise Inventory the work : Start from job architecture and competency groups; enumerate the critical skills per role. (Keep names human-readable.) Make expertise visible : Use skill flags (e.g., “Expert,” or “Mentor”) and publish them where managers and proposal teams actually look. Centralize discovery : One search box across skills, roles, competency groups, people, and content—rank by skill level, recency of validation, and project relevance. Also for resumes and CVs. Create an expert network : Let experts opt-in to mentoring, proposal reviews, “ask me” hours—with capacity signals to avoid overload. Require sign-offs for critical skills : Lightweight workflows where recognized experts validate that a colleague can perform a safety- or compliance-critical task. Close the loop : Capture evidence (project artifacts, assessments, reviews, training dates, etc.). Keep an audit trail: who validated whom, when, and why. (Helps with compliance framework evidence, such ISO/SOC 2, or industry specific audits.) Measure what matters : Track time-to-staff proposals, mean time-to-answer internal questions, mentor participation, % of critical roles with at least 2 experts, and audit exceptions. Where SkillsDB fits Powerful search across skills, job roles, and competency groups to surface people with exactly the right expertise—fast. And, across resumes, CVs, job descriptions, or any uploaded document. Skill flags to clearly delineate experts (and reviewers/mentors) at the skill and job-role level, discoverable in search. A visual skills matrix that shows all experts for any role, group, or the entire company—ideal for staffing, succession, and competence evidence. Expert sign-off flows that create provable records tied to people and skills—ready for audits and customer questionnaires. Finding experts isn’t just about efficiency—it’s about building confidence that your teams can deliver, adapt, and prove competence when it matters most. If you’d like to see how SkillsDB makes expertise easy to search, validate, and showcase, we’d be glad to walk you through it. Book a free demo. FAQs How does AI help me find the right expert faster? By unifying your skills, roles, competency groups, profiles, and project artifacts into a single search index, then ranking people by skill level, validation recency, and context (e.g., similar past projects). AI can also summarize profiles and suggest alternates if an expert is at capacity. Can an expert “game” the system by self-claiming skills? Require expert review/sign-off for critical skills and expire validations after a period or after major tech changes. Keep audit trails for who validated whom and why. Also, corroborate with manager grading of employee skills that can be a flag for inaccurate employee claims. How do we avoid overloading top experts? Use capacity signals (current load, mentoring slots) and “near-expert” alternates suggested by AI. Rotate reviews and reward participation. What about privacy and bias? Limit visibility of sensitive attributes; focus on skills and evidence. Review ranking features for bias; provide appeal mechanisms and human override. How often should expertise be re-validated? At a minimum, plan to re-validate critical skills and competencies once a year using skill surveys or assessment flows. For modern teams or fast-moving skills and competencies, consider a quarterly or bi-annual review (maybe even monthly) to keep pace with changes. Can we use this for mentoring and succession? Yes—publish opt-in mentor flags, track sessions, and pair near-experts with experts. NASA’s approach emphasizes continuity before retirements—good practice for any specialized team. What metrics should we watch? Time-to-staff proposals, MTTA (mean time to answer), % critical skills with ≥2 validated experts, rework rate, audit exceptions. Does this help with ISO 9001/ISO 27001/SOC 2? Yes. ISO 9001 Clause 7.2 requires documented evidence of competence; ISO 27001 7.2 expects competence for roles affecting the ISMS; SOC 2 auditors expect clear communication, training, and role-appropriate evidence under CC2.x. Expert sign-offs + audit trails support all three. What is a “corporate yellow pages” directory? In the late 1990s, global firms built “corporate yellow pages”—simple, searchable directories of internal experts—so a proposal manager in Frankfurt could find the exact microwave-antenna specialist in Singapore. Siemens’ ShareNet and Xerox’s Eureka are classic examples: they didn’t just store documents; they helped employees find the right people behind them, improving win rates and time-to-resolution. Today’s expert-finding tools are that idea—but with modern search, signals, and audit-ready proof. How do we prevent AI from “hallucinating” expertise? Ground the system in first-party, governed data (your skills and validations), restrict generative answers to cited sources, and show provenance (who signed off, when). Coveo’s 2025 EX report highlights employee skepticism when AI isn’t grounded. --- ## The Skills Matrix, Reimagined URL: https://skillsdb.com/blog/the-skills-matrix-reimagined The static skills matrix solved yesterday’s problems. Today’s global enterprises need more: agility, transparency, and AI-powered insights. That’s why we’ve rebuilt the skills matrix from the ground up—not as a spreadsheet, but as a living, interactive ecosystem. Here’s how SkillsDB transforms your skills matrix into a dynamic launchpad for workforce planning, training, and career growth. 1. Interactive Dashboards & Trend Switching Move beyond static tables. Switch between grades, log official training dates for safety or audits, see skill trends over time, and drill down by role, department, or geography. Harness a spike in “Mentor” flags, or a catch a dip in cybersecurity skills before it becomes a problem. Example: Need a mentor for a London project team? Filter Business Analysts to Power BI L3→L4 trend , ‘Mentor’ flag , training ≤90 days , and Manager endorsement —a few clicks, zero guesswork. 2. Skill Flags & Nuanced Ratings We go beyond the standard 1–5 scale with skill flags like Expert, Mentor, Interest, and Focus . They capture context—who’s ready to lead, who’s exploring new tech, who’s eager to coach others—making mentorship, staffing, and career mapping smarter. Imagine seeing a matrix of all your experts across the organization in one data-driven view. 3. Dynamic Charts & Graph Views Visualize distributions, gaps, and growth trajectories across teams and roles. Compare competencies across offices, run executive-level reports, and quickly assemble cross-functional teams based on real-time skill data. 4. Integrated Training Ecosystem Identify a gap and close it immediately. Search LMS content from all your vendors, SharePoint docs, YouTube tutorials, or professional courses from inside the matrix. Accept user-suggested resources, approve them, and make them searchable for all. The point of all this training data is to upskill your team and help their career paths. 5. Labels, Taxonomy & Flexible Organization Tag skills, roles, and training consistently. Track initiatives across departments or clients. Build your bespoke taxonomies that grow with the organization without losing structure. 6. Career Frameworks & Succession Planning Show employees exactly what skills they need to move from Analyst to Senior Analyst to Manager. Align learning paths with career ladders/levels to drive measurable progression and retention. Your employees want clarity on their career paths. 7. Powerful Analytics & AI-Ready Insights Spot trends, outliers, and plateaus. Our platform will recommend training, predict skill demand, and connect talent to projects—at enterprise scale. Why This Matters for Large Teams & Global Enterprises For enterprises managing thousands of people, SkillsDB offers a centralized-yet-decentralized source of truth. Everyone—HR, execs, managers, employees—contributes and benefits. Break down silos Make training spend strategic and useful Turn skills data into action Most importantly, the skills matrix becomes the starting point, not the end point of understanding skills and competencies—surfacing edge cases, hidden experts, and future leaders. The Road Ahead From factory floor charts to AI-driven analytics, the skills matrix has always aimed to connect the right people with the right work. But today’s environment demands more: interactive, inclusive, dynamic, and deeply connected to learning and career growth . SkillsDB’s reimagined matrix delivers that future now. If you’re ready to move beyond the spreadsheet era and build a true skills-first organization, book a demo and start scaling your learning culture. The future of skills management isn’t about documenting capabilities—it’s about activating them. SkillsDB’s reimagined matrix makes skills data actionable: driving staffing decisions, unlocking mentorship, guiding career paths, and fueling enterprise-wide agility. From trend-aware dashboards to AI-ready analytics, this isn’t just a new way to track skills—it’s the foundation of a skills-first organization. FAQ: The Skills Matrix, Reimagined Q: What makes the SkillsDB skills matrix “reimagined”? It combines interactivity, AI insights, training integration, and career frameworks—making the matrix a launchpad for growth, not just a static, record-keeping tool with stale data. Q: What are skill flags, and how are they used? Skill flags like Expert, Mentor, Interest, and Focus add context beyond proficiency ratings—helping leaders identify mentors, staff projects, and support career development. Q: How does the platform integrate with training? SkillsDB connects gaps directly to learning content—pulling from LMSs, SharePoint, YouTube, or user-suggested resources—so skills don’t just get tracked, they get developed. Q: How do employees benefit from the reimagined skills matrix? They gain clarity on career progression, visibility into skills needed for advancement, and access to training resources aligned with growth opportunities. Q: Why is this especially valuable for large enterprises? Because it scales seamlessly—giving thousands of employees and managers one shared source of truth, breaking silos, and turning skills data into enterprise-wide action. --- ## The Interactive Skills Matrix: From Static Grid to Mission Control for Global Teams URL: https://skillsdb.com/blog/the-interactive-skills-matrix The skills matrix started life as a paper chart on factory floors and evolved into a staple of workforce planning, talent development, and succession management. But in 2025, many organizations still rely on static spreadsheets that can’t keep up with changing skills, hybrid teams, and fast-moving business needs. Here, we explore the history of the skills matrix, why it still matters, and how SkillsDB has reimagined its AI-native, interactive skills matrix, turning a static grid into a dynamic launchpad for learning, career growth, and workforce planning. Why the Traditional Skills Matrix is Broken The classic skills matrix is powerful in theory but limited in practice: Static and slow: Skills evolve constantly, but spreadsheets demand tedious manual updates, and accurate data expires with time. Top-down only: Employees rarely get to update or interact with their own data. Shallow insight: Rows and columns hide patterns, outliers, and rising stars, which severely limits actual organizational utility. In a world where roles shift quickly, teams are global, and internal mobility is critical, a rigid HR document isn’t enough. The skills matrix has to become interactive, inclusive and engaging, trend-aware, organizationally holistic, and connected to learning . And, don’t forget—useful to both employees and managers—or it will quickly become useless. A Short History of the Skills Matrix The skills matrix first appeared in the mid-20th century on factory floors, sketched on large boards so supervisors could see who could do what and could reassign people quickly. 1990s: Healthcare, finance, IT, and education adopt the model for gap analysis , training, and scheduling. 2000s: Spreadsheets make updates easier and basic analytics possible. Cloud Era: SaaS platforms deliver real-time visibility, cross-site collaboration, and skills data for strategic planning. The goal hasn’t changed: get the right people in the right roles and help them grow. What’s changed is the complexity and speed of work—and that demands a new approach. What a Skills Matrix Does—And Why It Still Matters At its core, a skills matrix maps people vs. capabilities with clearly defined proficiency levels or training requirements. Done right, it should: Reveal who has what skills , and where the gaps are. Guide hiring, upskilling, and resource allocation for agile workforce planning. Create fairness and transparency , so opportunities go to those with the capability, not just the connections. Become a living skills inventory , supporting recruitment, performance reviews, and succession planning. Align strategy with capability , giving leaders visibility into workforce readiness for new technologies, markets, and change. With AI, the skills matrix can now auto-ingest assessments, flag anomalies, predict demand, and connect gaps directly to training and career paths. The skills matrix has come a long way from paper charts to digital spreadsheets—but static grids can’t keep pace with today’s workforce. To unlock true organizational agility, the matrix must be dynamic, interactive, and infused with AI. SkillsDB is transforming the skills matrix into a living system—one that not only reflects your workforce, but also empowers it. The result: more transparency, smarter decisions, and global teams ready for what’s next. Ready to see how an interactive, AI-powered skills matrix can transform your workforce planning? Book a demo with SkillsDB and start building your mission control for global teams. FAQ: The Interactive Skills Matrix Q: Why is the traditional skills matrix considered outdated? Because they’re static, slow to update, not updateable by the team, and hide meaningful patterns—leaving managers with outdated or shallow insights. Q: How does an interactive skills matrix differ from a static one? It updates in real time, engages employees directly, and provides organizational-level visibility across teams, roles, and locations, not to mention keeping the data current and useful. Q: What role does AI play in a modern skills matrix? AI automates data ingestion, surfaces anomalies, predicts future skill demand, and links training paths directly to gaps—making the matrix proactive rather than reactive. Q: Why does a skills matrix still matter in 2025? It remains the foundation for workforce planning, upskilling, recruitment, and succession planning—ensuring the right people are in the right roles. Q: How does a skills matrix help employees, not just managers? It empowers employees with visibility into their skills, career pathways, and training opportunities—creating fairness and boosting engagement. --- ## New Tools to Empower Your L&D Ecosystem URL: https://skillsdb.com/blog/new-tools-to-empower-your-l-d-ecosystem We're excited to share several compelling updates to the SkillsDB platform that directly address recent customer feedback and needs, each of which provides an exciting new tool for structured learning and driving end user engagement. Labels As organizations scale with SkillsDB, we've heard the need for more flexible ways to organize your skills data. Our new Labels feature brings a powerful new organizational tool to every corner of the system. Think of Labels as your digital filing system that works across all major system elements: Tag skills, roles, competency groups, training and more with consistent, custom identifiers you can manage from admin settings Create custom organizational schemes that match your company structure and needs Track initiatives across departments, projects, or customer segments Instantly filter and find related content across the platform with Label detail pages showing everything connected Book time with us today to see creative examples of how clients have started using SkillsDB Labels in their learning programs. Training Search At SkillsDB, we believe it’s critical to link learning and training resources to skills and competencies, regardless of where all of this content lives—whether in any of your LMSs, Sharepoint, Google Drive, internal servers, external professional training programs, or even YouTube or other video platforms. This platform-agnostic approach has been a game-changer for our customers who want to give their employees one place to see every available training resource, linked directly to their skill gaps or career pathway. Now, in addition to seeing training opportunities linked to profiles, users can also search across all training records based on keywords, training Labels, providers, cost, and connection to roles, career levels, and more. This change brings SkillsDB one step closer to being the ultimate home base for employees to seek out training and upskilling opportunities. User Suggested Training In addition to Training Search, end users can now also recommend training they believe will be useful to others via SkillsDB. The new user-suggested training feature empowers your entire organization to contribute to the learning ecosystem. Here's how it works: Employees and managers can directly submit training resources they discover Submissions include key details like price, provider, location, and more Admins maintain quality control through a streamlined approval process Approved content automatically integrates with your skills framework in SkillsDB All resources become instantly searchable and can be added to any person's learning plan Perspective + New Website: Our Vision for the Future We recently announced our completely reimagined website—the first major brand refresh in our 18-year history. But this isn't just a new coat of paint. At the heart of this transformation is our Perspective: our vision for the future of workplace learning and development. This represents our deep understanding of the challenges facing L&D teams today and our blueprint for solving them. We invite you to: Explore our new website and brand Read our Perspective to understand our vision (5-minute read) Share your thoughts and insights We're on a mission to make learning culture universal, transforming SkillsDB into Mission Control for L&D teams worldwide. Ready to see these new features in action? Book a demo or L&D consultation to explore training search, user-suggested training, and to see labels in action. Have questions about activating these new features in your account? Contact your Customer Success Manager or reach out to support@skillsdb.com for help. FAQ What are Labels in SkillsDB? Labels are custom tags you can apply to skills, roles, competency groups, training, and other system elements to create flexible organizational schemes. They work like a digital filing system, letting you instantly filter and find related content across the entire platform. How does Training Search work in SkillsDB? Training Search lets users search across all training records using keywords, Labels, providers, cost, and connections to roles or career levels. It surfaces every available training resource in one place, regardless of where the content lives — LMS, SharePoint, Google Drive, or external platforms. Can employees suggest training resources in SkillsDB? Yes. The User Suggested Training feature lets employees and managers submit training resources they discover. Admins review submissions through a streamlined approval process, and approved content automatically integrates with your skills framework and becomes searchable. What training platforms does SkillsDB integrate with? SkillsDB takes a platform-agnostic approach, linking training resources from any LMS, SharePoint, Google Drive, internal servers, external professional training programs, YouTube, and other video platforms. This gives employees one central place to see every available learning resource tied to their skill gaps or career pathway. How do Labels help organize skills data? Labels let you tag content with consistent, custom identifiers across all major system elements. You can track initiatives across departments, projects, or customer segments, and Label detail pages show everything connected to a given tag. What happens after a suggested training is approved? Once an admin approves a user-suggested training resource, it automatically integrates with your skills framework in SkillsDB. The resource becomes instantly searchable and can be added to any employee's learning plan. Can users search for training by cost or provider? Yes. Training Search supports filtering by keywords, training Labels, providers, cost, and connections to roles, career levels, and more. This makes it easy for employees to find relevant, affordable upskilling opportunities without leaving SkillsDB. How does SkillsDB link training to skill gaps? SkillsDB connects learning and training resources directly to skills and competencies in each employee's profile. Users see training opportunities linked to their specific skill gaps or career pathway, creating a clear development path. What is SkillsDB's mission for L&D teams? SkillsDB's mission is to make learning culture universal. The platform aims to be Mission Control for L&D teams, providing centralized tools for training search, skill development tracking, and employee-driven learning contributions. How do Labels differ from categories or folders? Unlike rigid categories, Labels can be applied across all major system elements — skills, roles, competency groups, and training — simultaneously. This cross-cutting approach lets you create custom organizational schemes that match your company structure and track initiatives across multiple dimensions. --- ## The New SkillsDB: Making Learning Culture Universal URL: https://skillsdb.com/blog/new-skillsdb-making-learning-culture-universal Today marks an exciting new chapter for SkillsDB. We've completely transformed our brand, marketing site, and product experience—but this change goes far deeper than aesthetics. It represents our renewed commitment to a bold mission: Make learning culture universal. Why Change? A Story of Evolution Working closely with L&D teams for almost 20 years has taught us something crucial: Building winning teams requires more than just tools—it needs a foundation of continuous learning and development. As we've grown to understand our customers’ challenges and aspirations more deeply, we realized we needed to evolve every aspect of how we present ourselves and our product. This transformation reflects a sharpened focus on helping L&D teams create environments where learning becomes integral to company culture, where skill development drives success, and where teams consistently reach their highest potential. Design Process The rebrand was a ground-up reinvention of our identity—a fresh start rooted in purpose and progress. Catalyzed by a major product overhaul, the brand overhaul gave us an opportunity to modernize and align our design language with where the core platform is headed. The process involved collaborative workshops, brand sprints, and deep design exploration. This included defining our core principles , clarifying our voice, and iterating through hundreds of visual concepts to land on a system that feels bold, connected, and enduring. The result is a cohesive and scalable identity, crafted with care, that reflects who we are and where we’re going. A Fresh Perspective on Learning Culture For years, L&D teams were promised a simple solution: massive libraries of content would automatically scale employee development. But this one-size-fits-all approach has proven ineffective, often creating employee cynicism rather than engagement. We've learned that true learning culture isn't built on content libraries alone—it's cultivated through intentional focused development strategies that align with both organizational goals and employee aspirations. Read more about our Perspective here . This transformation reflects our sharpened focus on helping L&D teams create environments where learning becomes integral to company culture, where the focus on skill development drives success, and where teams consistently reach their highest potential. A Skills-First Approach Our transformation is a fundamental shift in thinking. Instead of starting with content and trying to retrofit skills, we begin with the essential question: “What skills do we need, and what skills do we have?” This approach transforms how organizations understand and prioritize specific skills, measure and track skill development and manage and analyze learning outcomes. The Path Ahead With our new site, along with a completely new brand identity, we couldn't be more excited about the future. Our refreshed look reflects our bold vision while staying true to our core purpose: Empowering L&D teams to build genuine learning cultures that drive organizational success. FAQ What does "make learning culture universal" mean? It means creating workplace environments where continuous learning and skill development are embedded into daily operations, not treated as an afterthought. SkillsDB's mission is to help every L&D team build this kind of culture, regardless of organization size or industry. Why did SkillsDB rebrand after 18 years? The rebrand reflects a sharpened focus on helping L&D teams build genuine learning cultures that drive organizational success. After nearly two decades working with L&D teams, SkillsDB evolved its brand to align with a deeper understanding of customer challenges and a skills-first product direction. What is a skills-first approach to learning? Instead of starting with content libraries and retrofitting skills, a skills-first approach begins with the question: "What skills do we need, and what skills do we have?" This fundamentally changes how organizations prioritize skill development, measure progress, and manage learning outcomes. Why do content libraries alone fail for L&D? Massive content libraries promised to automatically scale employee development, but this one-size-fits-all approach proved ineffective. It often creates employee cynicism rather than engagement because it lacks intentional, focused development strategies aligned to organizational goals and individual aspirations. How does SkillsDB help L&D teams build learning culture? SkillsDB helps L&D teams create environments where learning is integral to company culture by providing tools that align skill development with business goals. The platform focuses on intentional development strategies rather than generic content delivery. What changed in the SkillsDB product experience? SkillsDB underwent a complete transformation of its brand, marketing site, and product experience. This included a ground-up reinvention of the visual identity, design language, and core platform capabilities to support skills-driven organizations. What is SkillsDB's Perspective document? The Perspective is SkillsDB's published vision for the future of workplace learning and development. It articulates the company's deep understanding of challenges facing L&D teams today and provides a blueprint for solving them through a skills-first approach. How does skills-first differ from content-first L&D? Content-first L&D starts with training libraries and tries to map them to skills after the fact. Skills-first L&D starts by identifying what skills the organization needs and has, then builds targeted development strategies around those gaps. This leads to more relevant, measurable outcomes. What drove the SkillsDB design process? The rebrand involved collaborative workshops, brand sprints, and deep design exploration. The team defined core principles, clarified their voice, and iterated through hundreds of visual concepts to create a cohesive, scalable identity aligned with the platform's direction. --- ## Skills-First Resource Planning URL: https://skillsdb.com/blog/skills-first-resource-planning Let’s End Resource Planning “Fire Drills” For too long, traditional resource planning has relied on spreadsheets and staffing “fire drills” that scramble to find the right people for new client proposals. There is a constant battle to answer resource planning questions for new client proposals. “Who do we have that’s fluent in Spanish, certified in PowerBI, and based in London?” Without clear visibility into skills and actual capabilities, new revenue opportunities are left at risk. Meanwhile, valuable expertise remains hidden within organizations, and skilled employees grow frustrated as their capabilities go unrecognized. This approach isn't just inefficient—it's unsustainable, which is why SkillsDB is leading the charge for what we call “Skills First” resource planning. Introducing Resume & Document Search in SkillsDB One of our latest resource planning innovations is the introduction of deep resume and document search in SkillsDB, allowing for side-by-side searches of resume documents along with structured skill and competency data. Contact us to learn how to enable this in your account . You can now instantly search thousands of resume documents using skill keywords and filters to surface team members based on potentially unreported skills and experience. Easily search for skills, competencies, interests, active certifications, clearances, coaching capabilities, and more. Whether you're looking for someone with security clearance, advanced coaching credentials, or a personal interest in sustainability or AI, this helps you uncover the right talent at the right time. All in one system-of-record. This means hidden talent can be discovered, knowledge silos can be broken, and projects can move forward with confidence. You’re not just filling a seat—you’re making the most of your people. And when it comes to proposal season or responding to urgent client needs, that difference is everything. Skills-First Resource Planning is the Future With skills-first resource planning, leaders can instantly locate team members with precise combinations of skills and experience—whether that's a Six Sigma Black Belt who speaks Mandarin, an experienced project manager with healthcare compliance expertise, or a senior developer with both cloud architecture and Azure experience based in New York City. Instead of relying on institutional knowledge, your team can instantly search for and find the best match based on real-time, verified skills data. Respond to opportunities faster, write stronger proposals with the right personnel in mind, and reduce last-minute scrambles. Companies that understand their workforce at a deeper level will move faster, staff smarter, and have better talent utilization, not to mention run more successful projects with better client outcomes. Schedule a call today to see how leading organizations are transforming their resource planning with SkillsDB. FAQ What is skills-first resource planning? Skills-first resource planning replaces spreadsheet-based staffing with real-time skills data to match the right people to projects and proposals. Instead of relying on institutional knowledge or last-minute scrambles, leaders instantly locate team members with precise combinations of skills, certifications, and experience. How does resume and document search work? SkillsDB's resume and document search lets you search thousands of resume documents using skill keywords and filters alongside structured skill and competency data. This surfaces team members based on potentially unreported skills and experience, breaking down knowledge silos. Why do traditional resource planning methods fail? Traditional resource planning relies on spreadsheets and institutional knowledge, creating staffing "fire drills" when new proposals arrive. Without clear visibility into actual workforce capabilities, revenue opportunities are left at risk and skilled employees grow frustrated as their expertise goes unrecognized. What can you search for in SkillsDB? You can search for skills, competencies, interests, active certifications, clearances, coaching capabilities, and more. Whether you need someone with security clearance, advanced coaching credentials, or a personal interest in sustainability, the system surfaces the right talent instantly. How does skills-first planning improve client proposals? Teams can respond to opportunities faster and write stronger proposals by instantly identifying the best-matched personnel based on verified skills data. This eliminates last-minute scrambles and ensures proposals showcase the right talent for each engagement. Can you combine multiple skill criteria in a search? Yes. Leaders can search for precise combinations — like a Six Sigma Black Belt who speaks Mandarin, or a senior developer with cloud architecture and Azure experience based in a specific city. The system supports multi-criteria searches across skills, certifications, location, and experience. How does SkillsDB uncover hidden talent in organizations? By combining structured skill profiles with deep resume and document search, SkillsDB surfaces capabilities that may not be formally documented in skill profiles. This breaks down knowledge silos and ensures valuable expertise within the organization is discoverable. What business outcomes does skills-first planning drive? Organizations that adopt skills-first resource planning move faster, staff smarter, and achieve better talent utilization. This leads to more successful projects, better client outcomes, and reduced costs from last-minute staffing scrambles. Is SkillsDB a system of record for skills? Yes. SkillsDB serves as a centralized system of record where all skills, competencies, certifications, and resume data are searchable in one place. This eliminates the need to check multiple systems or rely on managers' personal knowledge of team capabilities. How does skills-first planning reduce staffing fire drills? Instead of scrambling to answer questions like "who has this combination of skills and certifications," leaders search SkillsDB's real-time data to instantly surface qualified team members. This transforms reactive staffing into proactive workforce planning. --- ## The Magic of Career Pathways for Frontline Staff URL: https://skillsdb.com/blog/the-magic-of-career-pathways-for-frontline-staff Boost frontline staff retention with structured training programs, clear career pathways & skill validation to reduce turnover costs & improve productivity. Is your organization struggling to retain talented frontline workers? When frontline staff quit, over 50% cite the lack of a clear career path. According to Gallup, this turnover can cost up to 150% of their fully loaded salary when considering lost productivity, recruiting and training costs, not to mention safety risks, quality errors, and impact on morale. But there’s a proven answer: Structured training programs can boost retention by 40-50% within the first year, and often have the highest impact on frontline staff. The strongest results come from the commitment to provide two things: Tangible success profiles for each position Defined career pathways for leveling up For 18 years, we've helped organizations of all types create career-advancing training programs and build strong learning cultures. Click here to learn more about our proven approach: Create clear training progression for each role. Work with internal experts for each job function to define a proven path for entry-level staff to progress in their competence. Map out specific skills needed at each level. Start with concrete technical skills and map out development plans that will be crystal clear for staff. Over time, add assessment of soft skills and leadership competencies using concrete examples that show what you expect and what you want to reinforce in model employees. Set timeframes for the ideal progression path. Self-starters often advance quickly through clearly structured programs. Clear timelines and detailed tracking keep everyone focused on progression, without depending on personal initiative. Link each training milestone to concrete career advancement. When training requirements are met, promotion eligibility should activate automatically. Meaningfully defined training criteria helps take the guesswork out of promotion for both managers and staff and ensure fair and transparent advancement opportunities. Build in regular checkpoints and assessments. Regular skill assessments become career planning sessions, where managers and team members collaborate on next steps. These conversations ensure your frontline staff are actively progressing toward their career goals while meeting organizational needs, all through a robust skill assessment platform. Monitor and take action with certifications. Whether formal industry requirements, internal specializations, safety, or compliance, track all certifications and training requirements to ensure your team stays current and qualified for advancement. Centralize access to all training resources. Stop struggling with scattered training resources across multiple LMSs, spreadsheets, internal SOPs, and tribal knowledge. Bring together formal coursework, hands-on assessments, safety requirements, and compliance training into one easy dashboard. Team leads can easily track progress while employees access everything they need from a single tool. Validate skills through structured on-the-job training. Classroom learning and online courses only go so far. Integrate supervised hands-on practice, coaching from experienced team members, and documented skill validation. This ensures your people aren't just completing “click through” courses—they're mastering real-world applications of their training. The result? Motivated employees who understand exactly how they can advance their careers, and simplified tracking for your L&D, training, and compliance teams. Retention improves and productivity increases, all while building lasting institutional knowledge. A powerful skills training matrix built up from your career pathways is one of the most effective tools for implementing structured training, whether you have 30 employees or 3,000. The SkillsDB training matrix becomes your roadmap for talent development—tracking skills and certifications, identifying future leaders and capturing training records for compliance, while giving leadership real-time visibility and analytics into team capabilities. Ready to transform your frontline retention? Let's schedule 30 minutes, and we’ll show you how leading organizations approach structured training for frontline staff. ROI typically occurs within the first year through reduced turnover costs and improved productivity. Book a demo here to learn more. FAQ Why do frontline workers quit their jobs? Over 50% of frontline staff who quit cite the lack of a clear career path as a primary reason. According to Gallup, replacing a frontline worker can cost up to 150% of their fully loaded salary when factoring in lost productivity, recruiting, training, safety risks, and morale impact. How do career pathways reduce frontline turnover? Structured training programs can boost retention by 40-50% within the first year. The strongest results come from providing tangible success profiles for each position and defined career pathways for leveling up, giving employees a clear roadmap for advancement. What is a skills training matrix? A skills training matrix is a structured tool that maps required skills and certifications against employee capabilities for each career level. It serves as a roadmap for talent development, tracking skills, identifying future leaders, capturing training records, and giving leadership real-time visibility into team capabilities. How should you structure training progression for roles? Work with internal subject matter experts to define a proven path for entry-level staff to progress in competence. Start with concrete technical skills, then add soft skills and leadership competencies over time, using concrete examples of what you expect from model employees. Should training milestones link to career advancement? Yes. When training requirements are met, promotion eligibility should activate automatically. Meaningfully defined training criteria removes guesswork from promotions for both managers and staff, ensuring fair and transparent advancement opportunities. What role do assessments play in career pathways? Regular skill assessments become career planning sessions where managers and team members collaborate on next steps. These conversations ensure frontline staff actively progress toward their career goals while meeting organizational needs through structured checkpoints. Why centralize access to all training resources? Scattered training across multiple LMSs, spreadsheets, SOPs, and tribal knowledge creates confusion and inefficiency. Centralizing formal coursework, hands-on assessments, safety requirements, and compliance training into one dashboard lets team leads track progress while employees access everything from a single tool. How do you validate skills beyond online courses? Integrate supervised hands-on practice, coaching from experienced team members, and documented skill validation into your training program. This ensures employees are mastering real-world applications of their training, not just completing click-through courses. What certifications should frontline training programs track? Track all certifications including formal industry requirements, internal specializations, safety certifications, and compliance credentials. Monitoring these ensures your team stays current and qualified for advancement at every level. How quickly does structured training show ROI? ROI typically occurs within the first year through reduced turnover costs and improved productivity. Motivated employees who understand exactly how to advance their careers stay longer, while simplified tracking reduces the administrative burden on L&D, training, and compliance teams. What timeframes should career pathways include? Set ideal progression timelines for each career level so self-starters can advance quickly through clearly structured programs. Clear timelines and detailed tracking keep everyone focused on progression without depending solely on personal initiative. --- ## Skill Assessments Drive Learning Culture URL: https://skillsdb.com/blog/skill-assessments-drive-learning-culture Transform team development with intelligent assessment tools as pat of your skills development platform. As skill and competency projects become the norm, one challenge stands out. We call it the “ garbage in, garbage out ” problem. Once you’ve defined competency frameworks and skills profiles, how do you effectively track, assess, and nurture skills across your entire organization? And critically, how do you maintain the accuracy of this data over time? At SkillsDB, our answer to this challenge is a comprehensive assessment suite that transforms how you manage skill and competency data and development across your organization. This includes: Create role-based skill surveys . Deploy customized assessments based on job roles, competency groups, or general skills—ensuring relevant evaluation for every team member. Enable multi-level assessment . Combine manager assessments with self-evaluations through our self-assessment platform to create a complete picture of employee capabilities and potential. Track progress with dynamic scorecards . Generate point-in-time snapshots that capture assessment results, providing clear evidence of growth and development over time as a permanent record. Identify internal expertise . Easily flag top performers as mentors or subject matter experts, while allowing employees to indicate their own skill-based interests for on-the-job-training opportunities. Close skill gaps effectively . Automatically connect relevant learning resources to identified skill gaps, creating clear development pathways for every team member. Intelligent competency assessments enable : Benchmark skills against role requirements Plan strategic training based on skill analysis Automate email reminders to keep assessments on schedule Use comprehensive reporting for data-driven decisions Easily maintain high quality skill data Ready to transform how you develop and track skills across your organization? Schedule a demo or free consultation today to see how SkillsDB can empower your L&D initiatives. FAQ What is the "garbage in, garbage out" problem? It refers to the challenge of maintaining accurate skill and competency data over time. Even with well-defined competency frameworks, organizations struggle to effectively track, assess, and keep skills data current — and bad data leads to bad development decisions. How do skill assessments drive learning culture? Skill assessments create a continuous feedback loop between identifying capability gaps and delivering targeted development. By regularly evaluating skills against role requirements, organizations build a culture where data-driven improvement replaces guesswork. What types of assessments does SkillsDB support? SkillsDB supports role-based skill surveys customized by job roles, competency groups, or general skills. It also enables multi-level assessment, combining manager evaluations with employee self-assessments to create a complete picture of capabilities and potential. How do dynamic scorecards track employee progress? Dynamic scorecards generate point-in-time snapshots that capture assessment results as a permanent record. Over time, these snapshots provide clear evidence of growth and development, letting L&D teams measure the impact of training investments. Can assessments identify internal mentors and experts? Yes. SkillsDB lets you flag top performers as mentors or subject matter experts based on assessment data. Employees can also indicate their own skill-based interests for on-the-job training opportunities, making internal expertise discoverable across the organization. How do assessments connect to learning resources? SkillsDB automatically connects relevant learning resources to identified skill gaps from assessments. This creates clear development pathways for every team member, ensuring training is targeted rather than generic. What does benchmarking skills against role requirements mean? Benchmarking compares an employee's current skill levels against the defined requirements for their role. This reveals exactly where gaps exist, allowing L&D teams to plan strategic training based on real data rather than assumptions. Can assessment reminders be automated in SkillsDB? Yes. SkillsDB automates email reminders to keep assessments on schedule. This ensures regular evaluation cycles happen consistently without manual follow-up, maintaining the quality and currency of your skills data. What is multi-level assessment in skills management? Multi-level assessment combines manager evaluations with employee self-assessments to create a more complete and balanced view of capabilities. This dual perspective reduces bias and identifies blind spots that either party alone might miss. How do assessments support data-driven L&D decisions? Comprehensive assessment reporting provides the data foundation for strategic training planning. L&D teams can identify organization-wide skill gaps, track development trends over time, and allocate training budgets based on actual needs rather than intuition. --- ## 2024 Year in Review URL: https://skillsdb.com/blog/2024-year-in-review We cover a bunch of exciting features released during the year, and setup for a brilliant 2025. As we reflect on 2024, we are full of gratitude and excitement for the extraordinary achievements made possible, thanks in part to you. This past year marked a pivotal shift for SkillsDB—a year where we reimagined the very essence of what’s achievable for skills-based organizations and charted our course for the future. After 16 years of growth, listening to customer and user feedback, and thorough exploration into the evolving dynamics of our industry, we embarked on a ground-up redesign of our SaaS platform. With 18 months of unwavering dedication, we delivered a completely rebuilt, cutting-edge platform, engineered to empower skills-driven organizations to build winning teams. Here are some of the key advancements that made 2024 truly exceptional: Launched a revolutionary, ground-up redesigned and rebuilt platform, leveraging a state-of-the-art modern tech stack Introduced entirely new analytics, charts, and graphs, empowering L&D teams to gain profound insights across the organization and pinpoint training vulnerabilities Implemented smarter, more intuitive mechanics for organizing skills into advanced job roles and competency groups, enhanced employee skills summary pages, and upgraded grading workflows with manager-definable benchmarks Developed enhanced, powerful tools to seamlessly align customer job frameworks and competency-based career ladders, supporting a structured competency based training program that drives organizational growth Created upskilling pages, dedicated to each skill for centralizing critical learning resources and relevant connected content, fostering a culture of continuous improvement Rolled out a new, streamlined skills survey workflow for regular employee self-assessments and manager evaluations Overhauled email notifications across nearly all functionality, providing timely reminders for completion, expiration, and other crucial actions like closing out regular assessments Deployed a new method to seamlessly connect internal subject matter experts and mentors to specific skills, enabling easy discovery through robust search Unveiled an entirely new, highly efficient workflow for certifications, complete with proactive expiration notifications Delivered a flexible, new skills matrix for job roles and competency groups, alongside a comprehensive training matrix, clearly showcasing when employees are trained on specific skills. Implemented a system-wide search that enables instant access to all data, including experts, mentors, skill grades, roles/groups, certifications, geography/division/shift, and more Every feature was meticulously crafted and designed with one singular goal in mind: to empower you in building winning teams. As we look at the 2025 roadmap, our commitment to delivering rapid innovation and sustained improvement remains unwavering. This quarter, we’ll be unveiling a completely reimagined, purpose-built marketing website that embodies an even sharper vision for SkillsDB and showcases our strengthened dedication to our customers’ success. Thank you for being an indispensable part of our journey. We look forward to an incredibly useful, prosperous and forward leaning 2025! FAQ What did SkillsDB release in 2024? SkillsDB delivered a completely rebuilt platform from the ground up using a modern tech stack. Key releases included new analytics and reporting, advanced job role and competency group tools, a streamlined assessment workflow, overhauled certifications, skills and training matrices, and system-wide search. Why did SkillsDB rebuild its entire platform? After 16 years of growth and customer feedback, SkillsDB undertook an 18-month ground-up redesign to deliver a cutting-edge platform engineered for skills-driven organizations. The rebuild leveraged a modern tech stack to support the evolving needs of L&D teams. What new analytics features were added in 2024? SkillsDB introduced entirely new analytics, charts, and graphs that empower L&D teams to gain deeper insights across the organization. These tools help pinpoint training vulnerabilities and track development trends at the organizational level. How did SkillsDB improve its assessment workflow? SkillsDB rolled out a new streamlined skills survey workflow for regular employee self-assessments and manager evaluations. The platform also overhauled email notifications across nearly all functionality, providing timely reminders for assessment completion, expiration, and other critical actions. What is the SkillsDB skills matrix? The skills matrix is a flexible tool for job roles and competency groups that maps employee capabilities against role requirements. SkillsDB also delivered a comprehensive training matrix alongside it, clearly showing when employees are trained on specific skills. How does system-wide search work in SkillsDB? System-wide search enables instant access to all data across the platform, including experts, mentors, skill grades, roles, groups, certifications, geography, division, shift, and more. It eliminates the need to navigate through multiple screens to find specific information. What changed with certifications in SkillsDB? SkillsDB unveiled an entirely new, highly efficient certification workflow complete with proactive expiration notifications. This ensures teams stay current on required certifications without manual tracking or follow-up. How did SkillsDB improve skill organization in 2024? The platform implemented smarter, more intuitive mechanics for organizing skills into advanced job roles and competency groups. This included enhanced employee skills summary pages and upgraded grading workflows with manager-definable benchmarks. What are upskilling pages in SkillsDB? Upskilling pages are dedicated pages for each skill that centralize critical learning resources and relevant connected content. They foster a culture of continuous improvement by giving employees a single destination for all development resources tied to a specific skill. Can SkillsDB connect mentors and experts to skills? Yes. SkillsDB deployed a new method to seamlessly connect internal subject matter experts and mentors to specific skills. These connections are discoverable through robust search, making it easy for employees to find the right people for guidance and knowledge transfer. --- ## What Is a Skills-Based Organization? Definition, Benefits, and How to Become One URL: https://skillsdb.com/blog/what-does-it-mean-to-be-a-skills-based-organization Skills-based organizations are gaining popularity as the modern approach for successful businesses. Learn what it means. In today's rapidly changing business environment, organizations recognize the importance of being agile and adaptable with changes from technology, market demands and economic trends. One area receiving increased attention is how best to leverage employee skills to drive employee growth, increased organizational success and ultimately learning culture. The concept of skills-based organizations is gaining recognition as a modern and practical approach to helping L&D teams manage human resources and achieve organizational goals. Becoming a skills-based organization is crucial to driving employee success and staying competitive. To achieve this, it’s vital to have a clear understanding of what it means to be a skills-based organization, and the benefits it offers. In this article, we will explain what it means to be a skills-based organization. From this, you can make informed decisions about how to cultivate and utilize the skills of your workforce to drive success. Definition: What is a Skills Based Organization? A skills-based organization is one that focuses on competencies and skills (also historically known as competency-based management). It breaks down classic job descriptions and hierarchical structures, and its processes are deliberately adapted to the specific talents of employees. There is less focus on the primary job description (and/or job role ) and its related skills, and more focus on how the wealth of skills of each employee is utilized for the growth of the organization. Speaking in an interview by myHRfuture, Susan Cantrell, Deloitte's VP of Workforce Strategies, said “work is no longer a 1-to-1 relationship between employees and jobs, but a many-to-many relationship between work and skills, and that opens up all kinds of new opportunities for both the organization and workers.” Instead of structuring work in terms of specific job roles, work is broken down into projects and tasks with specific skill requirements. Employees with the right match of skills are added to the tasks where their skills can be best utilized. Initially, employees may be hired for job roles, but would not be restricted to their role. Speaking further on this, Susan Cantrell said “workers can take a percentage of their time, they’re still performing their core jobs, but then they can flow anywhere in the organization to projects and tasks.” A recent Deloitte survey demonstrates that this approach is already gaining traction. Of the executives who responded, "63% say work in their organizations is currently being performed in teams or projects outside of people’s core job descriptions.” In a fully skills-based approach, organizations abandon job roles altogether. Work becomes structured according to the needs of the organization (broken down into projects and tasks), and the skills of employees. With this approach, the organization creates an internal marketplace of skills, from which they can draw the best talent to execute projects according to market trends and business needs. This creates an ever-evolving need for employee skill tracking, upskilling, reskilling, and cross-skilling. What Skills Are Considered? In a skills-based organization, it is important to track core technical skills, such as specifics in coding, marketing, and management. These form the basis of the services or products the organization offers. However, it is just as important to track and utilize soft skills , such as creativity and leadership as these can play a pivotal role in driving the overall success of business initiatives and endeavors. Skills-based organizations make it a practice to identify, track, and nurture technical skills, but they also give equal attention to soft skills which may be more subtle and difficult to measure. What Are the Characteristics of a Skills-Based Organization? A skills-based organization is characterized by several key principles that prioritize the development and utilization of its employees' skills. Skills Identification and Tracking A skills-based organization cannot exist without a software platform to manage it all. To implement a skills-based approach, organizations must invest in robust systems and processes for skill identification and tracking. This involves assessing and documenting the skills possessed by each employee and creating a comprehensive skills inventory . Skills Focused Work Allocation A skills-based organization utilizes its employees' skills rather than relying solely on job titles or seniority. Employees are recognized and assigned work based on their combination of technical and soft skills, and not based on rigid roles with predefined tasks. This also helps eliminate unwanted biases from the workplace. As each employee works in the organization, data about their behaviors, abilities, and knowledge is tracked, along with skills development over time. Each employee's future work and career development is based on their demonstrated competency. Talent Management Talent management is also strongly emphasized, as the organization focuses on attracting, retaining, and developing the best talent within its workforce. For optimal results, companies may use a framework like Deloitte's talent management maturity model, the SkillsDB competency framework, or other skills tracking tools to implement practices and processes. Employee Development Employee development is paramount in a skills-based organization. It provides opportunities for employees to develop and improve through training, coaching, and mentoring programs. The organization invests in developing its capable workforce and preparing for the future of workforce development. Skills-Based Volunteering Organizations may utilize the skills-based volunteering organization model, allowing employees to contribute their skills to the community. Ultimately, a skills-based organization is focused on building the workforce of the future as it promotes skill-based jobs and encourages employees to self-identify their proficiencies. By doing so, employees inform the organization of the myriad of ways that they can contribute to a stable, successful workforce. Benefits of a Skills Based Organization There are several benefits of becoming a skills-based organization, including: Increased productivity and performance. By focusing on the skills and abilities of employees, a skills-based organization can ensure that the right people are in the right jobs, leading to increased productivity and performance. Attraction and retention of top talent. A skills-based organization that prioritizes employee development and career progression is more likely to attract and retain the best talent. Improved employee engagement and satisfaction . Employees who feel valued and challenged in their work are more likely to be engaged and satisfied. This is better achieved when employee skills and competencies are fully utilized. Better alignment of skills with business goals . By focusing on skills and abilities, a skills-based organization can better align the skills of its workforce with its business goals and needs. Greater flexibility and adaptability . A skills-based organization is better equipped to adapt to changing business needs and respond to new opportunities as they arise. Employees can flow from one project to another based on their skills, creating a system that is primed for change and future growth. Improved employee development . A skills-based organization investing in its employee development is more likely to cultivate a highly skilled and capable workforce. Increased Innovation . By focusing on skills and abilities, a skills-based organization can tap into its employees' unique strengths and perspectives, leading to increased innovation and creativity. Transitioning to a Skills Based Organization A skills-based organization is a model that prioritizes the skills and abilities of employees in all aspects of the organization. It is the wave of the future. This approach offers numerous benefits, including increased productivity and performance, attraction and retention of top talent, improved employee engagement and satisfaction and greater flexibility and adaptability. However, despite its many benefits, implementing a skills-based organization can present several challenges, including resistance to change, difficulty in assessing employee skills, investment in a training and development platform, and misalignment of skills with business goals. If you'd like to learn more, or to see how SkillsDB helps some of the world's leading companies transition to a skills-based organization, book a demo here . FAQ What is a skills-based organization? A skills-based organization focuses on employee competencies and skills rather than rigid job descriptions and hierarchical structures. Work is broken down into projects and tasks with specific skill requirements, and employees are matched based on their capabilities rather than their title. How does a skills-based organization allocate work? Instead of assigning work based on job titles or seniority, a skills-based organization matches employees to projects and tasks based on their combination of technical and soft skills. Employees can flow anywhere in the organization where their capabilities are needed, not just within their core job description. What skills matter in a skills-based organization? Both core technical skills and soft skills matter equally. Technical skills form the basis of products and services, while soft skills like creativity and leadership drive the overall success of initiatives. Skills-based organizations make it a practice to identify, track, and nurture both categories. What are the benefits of becoming skills-based? Key benefits include increased productivity and performance, better attraction and retention of top talent, improved employee engagement, stronger alignment of skills with business goals, greater organizational flexibility, and increased innovation by tapping into employees' unique strengths. Why do skills-based organizations need software platforms? A skills-based organization cannot exist without a platform to manage skills identification, tracking, and development at scale. The system must assess and document each employee's skills, create a comprehensive skills inventory, and support ongoing gap analysis and training alignment. How does skills-based work differ from traditional roles? In traditional organizations, employees are confined to predefined job descriptions. In a skills-based model, work becomes a many-to-many relationship between tasks and skills. Employees still perform core jobs but can flow to projects and tasks across the organization based on their capabilities. What percentage of work happens outside job descriptions? According to a Deloitte survey, 63% of executives say work in their organizations is currently performed in teams or projects outside of people's core job descriptions. This trend toward skills-based work allocation is accelerating across industries. What challenges arise when transitioning to skills-based? Common challenges include resistance to change, difficulty in accurately assessing employee skills, the investment required in training and development platforms, and potential misalignment of skills with business goals. These are manageable with the right platform and change management approach. How does skills tracking improve employee retention? Employees who feel valued and challenged are more engaged and satisfied. When an organization tracks and utilizes the full range of employee skills and competencies, it creates career progression opportunities and ensures people are in roles where they can contribute meaningfully. What is skills-based volunteering in organizations? Skills-based volunteering allows employees to contribute their professional skills to community initiatives, extending the skills-based model beyond internal projects. It encourages employees to self-identify proficiencies and demonstrates the organization's commitment to leveraging talent for broader impact. How do skills-based organizations handle talent management? They strongly emphasize attracting, retaining, and developing the best talent using frameworks like competency models and skills tracking tools. Each employee's career development is based on demonstrated competency rather than tenure, with data about abilities and knowledge tracked over time. What is an internal skills marketplace? In a fully skills-based approach, organizations create an internal marketplace of skills from which they can draw the best talent for projects based on market trends and business needs. This creates an ever-evolving need for upskilling, reskilling, and cross-skilling across the workforce. --- ## Major Features Release for SkillsDB URL: https://skillsdb.com/blog/major-features-release-for-skillsdb We are excited to announce our latest feature release—one that is a long-time coming—which includes several improvements designed to make SkillsDB more straightforward, efficient and easier to use. Welcome to SkillsDB, the hub for employee success and a leading skills management platform . We help create skills-based organizations by managing employee skills and skills gaps, training and competencies. We are excited to announce our latest feature release - one that is a long-time coming - which includes several improvements designed to make SkillsDB more straightforward, efficient and easier to use. First, we've made significant changes to the navigation. Now, you’ll find a left navigation bar that divides some of the core functionality, making finding what you're looking for much more accessible. Each item on the left bar represents features that used to be pop-ups or scattered throughout. By segmenting them, we've made everything more intuitive to navigate. The second major piece to the update is a modern-looking user interface that is more uniform across all of SkillsDB. We focused on simplicity and ease-of-use. The result is a sleek, modern, intuitive and an aesthetically pleasing look. As part of this, we have standardized table functions: Adding, editing and deleting a record can be found in the table title above the header row, as well as free text searching There is now direct access to the column chooser, sorting and column filtering at the top right of every table, to help sift through data If you need advanced sorting or advanced filtering, that’s now located at the top right of every table as well The third element to this update is contextual help throughout SkillsDB. Accessed from the help icon at the top right, this provides helpful information and guidance relevant to any page. With this, users can access help content specific to where they are in SkillsDB, which means they can quickly get the help they need without leaving the page. With these updates, we're confident SkillsDB will be even more valuable and easier to use than ever before. If you have any questions, please feel free to reach out to us by going to help.skillsdb.com or send an email to support@skillsdb.com . FAQ What changed in the SkillsDB navigation? SkillsDB introduced a left navigation bar that segments core functionality into clearly organized sections. Features that were previously pop-ups or scattered throughout the interface are now accessible from dedicated navigation items, making everything more intuitive to find. How were SkillsDB tables standardized? All tables now follow a consistent pattern: add, edit, and delete actions are in the table title above the header row alongside free-text search. Column chooser, sorting, and filtering controls are located at the top right of every table, with advanced sorting and filtering available from the same location. What is contextual help in SkillsDB? Contextual help provides page-specific guidance accessible from the help icon at the top right of any screen. Users get relevant information and instructions for exactly where they are in SkillsDB, without needing to leave the page or search through external documentation. What does the updated SkillsDB interface look like? The updated interface features a sleek, modern, and uniform design across the entire platform. The focus was on simplicity and ease of use, resulting in an aesthetically pleasing look that is consistent regardless of which feature you are using. How do you filter data in SkillsDB tables? Every table provides direct access to column chooser, sorting, and column filtering at the top right. For more granular control, advanced sorting and advanced filtering options are available in the same location, letting you sift through data efficiently. Where do you find add and edit actions in SkillsDB? Adding, editing, and deleting records can be found in the table title area above the header row of every table. Free-text searching is also located in this same area, providing a consistent experience across all features. How do you get help inside SkillsDB? Click the help icon at the top right of any page to access contextual help content specific to that screen. You can also visit help.skillsdb.com or email support@skillsdb.com for additional assistance. What is SkillsDB used for? SkillsDB is a skills management platform that helps organizations create skills-based workforces by managing employee skills, identifying skills gaps, tracking training, and organizing competencies. It serves as a central hub for employee success and development. --- ## 8 Reasons You Need to Build Mentoring into Company Culture URL: https://skillsdb.com/blog/8-reasons-you-need-to-build-mentoring-into-company-culture Read about critical factors that support bringing mentoring into company culture. We live and work in a time when the need for mentors is greater than ever. With so much uncertainty and change in the world, mentorship can provide stability and guidance for your team during challenging times. The benefits of mentorship are well-documented, and yet many organizations still don't have formal mentoring programs in place. Mentorship can be a powerful tool for professional development, helping employees learn new skills and grow in their careers. For businesses, mentoring can contribute to a more engaged and productive workforce. It can also help with succession planning , by identifying and developing high-potential employees who can take on leadership roles in the future. There are many reasons why mentorship is essential to company culture. Here are 8 of the most important: Mentoring can help to develop and retain talent Mentoring can be an important part of an employee's development journey, and an important part of an employee training platform. By pairing employees with more experienced mentors, businesses can give them the opportunity to learn new skills and knowledge. This can help to retain talent within the organization, as employees feel supported in their development. In fact, 94% of workers say that they would stay at a company longer if it invested in their career development. In addition, mentoring can help employees progress in their careers, providing them with the opportunity to take on new challenges and responsibilities. As a result, businesses can benefit from a more engaged and productive workforce. Mentoring can improve engagement and productivity Mentoring can improve engagement and productivity in the workplace by providing employees with a sense of purpose and direction. It can help employees to feel more supported in their roles, and motivate to better achieve their goals. In fact, companies with engaged employees are 17% more productive than those that don’t. Many businesses struggle with employee engagement, but mentoring can be a simple and effective solution. By investing in mentorship, businesses can create a more positive work environment and culture. Most importantly, mentoring relationships can act as a source of support, helping employees feel motivated and connected to their work, which is much-needed in times of stress and change. Mentoring can build trust and understanding Trust and understanding are essential for any workplace relationship, and mentoring relationships are no different. Trust is one of the key elements that makes mentoring so effective. When mentors and mentees build trust, they create a safe environment where they can openly share ideas, thoughts, and feelings. As a result, they can develop a deeper understanding of each other and their respective perspectives. In today’s workplace, it’s more important than ever to build trust and understanding. With so much change and uncertainty, employees need to feel that they can rely on their mentors for support. By investing in mentorship, businesses can create a workplace culture of trust and understanding. Mentoring can improve communication Mentoring can provide a space for open dialogue between mentors and mentees, helping improve communication. In order to build trust and understanding, it’s important for communication to be clear and efficient. Mentoring helps by giving employees the opportunity to share their thoughts and ideas openly, without fear of judgment. This enables employees to develop better communication skills, which can be beneficial in other areas of their lives. In addition, mentoring can help employees understand different communication styles. By being exposed to different ways of communicating, employees can learn how to adapt their own communication style to suit different situations. This is an important skill in the workplace, where employees often need to communicate with people from different backgrounds and with different communication styles. Mentoring can foster creativity and innovation Mentoring can create an environment where creativity and innovation flourish. When mentors and mentees share their ideas openly, they can challenge each other to think outside the box. This can lead to the development of new and innovative ideas, which benefits the business as a whole. In order to foster creativity and innovation, businesses need to create an environment where employees feel comfortable sharing their ideas. Mentoring can be a great way to do this, as it provides employees with a safe space to share their thoughts. By investing in mentoring, businesses can encourage creativity and innovation in the workplace. Mentoring can provide support during times of change Times of change can be difficult for employees, but mentoring can provide much-needed support. Mentors can act as a sounding board for their mentees, helping them to make sense of change and navigate through the difficult times. In addition, mentors can provide guidance on how to cope with change, both personally and professionally. Organizations are constantly changing, whether a change in leadership, change in strategic direction, or a change in the way things are done. These changes can be disruptive and stressful for employees. Mentoring can help employees to cope with change by providing support and guidance. Mentoring can improve job satisfaction Mentoring can improve job satisfaction by providing employees with a sense of purpose and belonging. When employees feel connected to their work, they are more likely to be satisfied with their job. Mentoring can help employees to feel connected to their work by providing guidance and support. In addition, mentoring can help employees to develop a better understanding of their role within the company. Organizations that invest in mentoring often see an improvement in job satisfaction levels. This is because mentoring helps employees feel more connected to their work and to the company as a whole. As a business, improving job satisfaction should be a priority, and mentoring is a great way to do this. Mentoring can develop leadership skills Mentoring can help employees to develop leadership skills by providing them with the opportunity to learn from their mentors. Mentees can observe their mentors and learn how they handle different situations. In addition, mentees can learn about different leadership styles and approaches. By learning from their mentors, mentees can develop their own leadership skills. Leadership skills are important for all employees, not just those in management positions. By investing in mentoring as part of a skills development program, businesses can help their employees to develop leadership skills. These skills will be beneficial in all areas of their lives, both personal and professional. The Bottom Line Mentoring can be a valuable tool for businesses, providing many benefits, such as improved engagement and productivity, increased trust and understanding, and fostering innovation. While mentoring can take some time to implement, the long-term benefits can be well worth the investment. FAQ Why is mentoring important in company culture? Mentoring provides stability and guidance during uncertain times, helps develop and retain talent, and contributes to a more engaged and productive workforce. It also supports succession planning by identifying and developing high-potential employees for future leadership roles. How does mentoring improve employee retention? 94% of workers say they would stay at a company longer if it invested in their career development. Mentoring pairs employees with experienced guides who help them learn new skills and progress in their careers, directly addressing the development investment employees value. What impact does mentoring have on productivity? Companies with engaged employees are 17% more productive than those without. Mentoring improves engagement by providing employees with a sense of purpose, direction, and support in their roles, which translates directly into higher productivity. How does mentoring build trust in the workplace? When mentors and mentees build trust, they create a safe environment for openly sharing ideas, thoughts, and feelings. This deepens mutual understanding and perspectives, creating a workplace culture of trust that is especially valuable during times of change and uncertainty. Can mentoring improve communication skills at work? Yes. Mentoring provides a space for open dialogue where employees can share thoughts without fear of judgment. Exposure to different communication styles helps employees learn to adapt their own style to suit different situations, a critical skill in diverse workplaces. How does mentoring foster creativity and innovation? When mentors and mentees share ideas openly, they challenge each other to think outside the box. Mentoring creates a safe space for sharing new ideas, which can lead to innovative thinking that benefits the entire organization. Does mentoring help employees during organizational change? Yes. Mentors act as a sounding board for mentees during transitions, helping them make sense of change and navigate difficult periods. They provide guidance on coping with change both personally and professionally, whether it involves leadership shifts, strategy changes, or process updates. How does mentoring develop leadership skills? Mentees learn leadership by observing how their mentors handle different situations and by exposure to various leadership styles and approaches. These skills benefit all employees, not just those in management positions, strengthening the organization's leadership pipeline. Does mentoring improve job satisfaction levels? Yes. Mentoring helps employees feel connected to their work and the company by providing guidance, purpose, and belonging. Organizations that invest in mentoring consistently see improvements in job satisfaction, which reduces turnover and improves overall morale. How does mentoring support succession planning? Mentoring identifies and develops high-potential employees who can take on leadership roles in the future. By pairing emerging talent with experienced leaders, organizations build a pipeline of capable successors ready to step into critical positions. What are the long-term benefits of workplace mentoring? Long-term benefits include improved engagement and productivity, increased trust and understanding across teams, greater innovation, stronger leadership pipelines, and higher job satisfaction. While mentoring takes time to implement, these compounding benefits make it one of the highest-ROI development investments. --- ## Everything You Need to Know About ISO and Skills Management URL: https://skillsdb.com/blog/everything-you-need-to-know-about-iso-and-skills-management Read about how some ISO standards and skills management are tightly connected. Our world is increasingly globalized and interconnected. In order to maintain a level of quality and consistency, many organizations rely on the standards set by the International Organization for Standardization (ISO). ISO is an independent, international organization that develops and publishes standards for a wide range of products and services. Established in 1947, ISO currently has over 16,500 standards that are used in 159 countries. One of the most important aspects of ISO standards is skills management. To ensure products and services are of the highest quality, it is essential to have a properly trained workforce knowledgeable about the relevant ISO standards. ISO-certified organizations are required to have skills management systems that meet the needs of their employees and customers. They must also ensure their systems are up-to-date and compliant with ISO standards. In today’s evolving workplace, many companies are turning to a skills management platform to simplify how they track and enhance employee competencies in line with ISO requirements. In order to ensure your workforce has the necessary skills, you need to have a robust skills management system in place. A good skills management system will help identify the skills your employees need, bring clarity to skills gaps, and tie training to those gaps (or develop necessary training programs internally, or with vendors) so employees are properly equipped to meet the requirements of ISO standards. There are a few different ISO standards pertaining to skills management, including ISO 9001, ISO 10018, ISO 14001 and ISO 17024. ISO 9001 is a a set of standards to help organizations ensure they are providing products and services meeting customer requirements. To become ISO certified, organizations must go through a rigorous auditing process. Part of this process includes demonstrating they have adequate skills management systems in place, especially clause 7.2. ISO 10018 provides guidance on engaging people in an organization's quality management system, and on enhancing their involvement and competence within it. Any organization, regardless of size, type, or activity benefits from following its guidelines. ISO 14001 helps organizations improve environmental performance through efficient resource use, waste reduction and sustainability. ISO 17024 is an international standard providing guidelines for the certification of individuals. Organizations which offer certification programs must meet the requirements of ISO 17024 in order to be accredited. This standard covers a wide range of topics, including the development of certification programs, the assessment of candidates, and the issuance of certificates. When it comes to skills management, ISO 9001, 10018,14001 and 17024 are the most important standards to be aware of. By understanding these standards and how they relate to skills management, you can ensure that your organization is providing employees with the training and development opportunities they need to be successful. Many businesses now adopt training and development platforms that align employee growth with ISO-compliant frameworks. There are several key elements to consider during the planning of your skills management system. Here are some of the most important things to keep in mind: Identify the required employee skills The first step in developing a skills management system is to identify the required employee skills. You will need to consider the specific ISO standards relevant to your business, and identify those skills your employees will need to comply with these standards. Identify the skills available Next, you will uncover the skills available amongst employees in your organization. This can be done with employee interviews, questionnaires, or by employees and/or managers during this skills assessment phase. Determine the skills gaps After you identify the required skills and the available employee skills, the next critical step is to identify the gaps present between the two. The outcome of this process determines the best growth path and, in the case ISO compliance, meeting the standards. Establish training to close skills gaps Closing skills gaps occurs by directing employees to training materials and tracking their progress. If you don’t have the necessary training programs available, you will need to develop them (or work with a vendor). Tracking employee training progress is critical for ISO compliance. The type of training you provide depends on the specific skills needed. Implement, evaluate and update the skills management system After you have rolled out training programs, it is time to implement a skills management system. This involves creating procedures and processes for tracking employee skills, managing the skills gaps, and ensuring employees are properly trained. There is a great deal of complexity to deal with here, and it is an iterative process.Ultimately, this is an important component to meet the requirements of ISO standards. An effective employee skills platform allows organizations to continuously monitor and improve workforce capability, staying ahead of ISO compliance requirements. Conclusion A skills management system is an essential part of any organization needing to ensure compliance with ISO standards. By understanding the requirements of ISO 9001, ISO 10018 and ISO 17024, you can develop a system to help train your employees to meet these standards. There are many benefits to becoming ISO-certified, including improved customer satisfaction, increased efficiency, and reduced costs. ISO-certified organizations are also more likely to win new customers and contracts. If you want to learn more about skills management, or if you are interested in ISO certification as it relates to skills management, contact us today . SkillsDB is a hub for employee success, delivering skills management platform to help ensure compliance with ISO standards. Be sure to visit our website , where you can learn more about our SaaS platform and get started on the path to ISO certification. FAQ How do ISO standards relate to skills management? ISO-certified organizations are required to have skills management systems that ensure their workforce is properly trained and knowledgeable about relevant standards. Standards like ISO 9001 specifically require demonstrating adequate skills management systems during the auditing process. What is ISO 9001 and why does it matter? ISO 9001 is a set of standards ensuring organizations provide products and services that meet customer requirements. Its clause 7.2 specifically requires organizations to demonstrate adequate skills management systems during the rigorous certification audit process. What ISO standards apply to skills management? The most relevant standards are ISO 9001 (quality management and customer requirements), ISO 10018 (people engagement and competence in quality management), ISO 14001 (environmental performance and resource efficiency), and ISO 17024 (certification of individuals). Each has specific implications for how organizations track and develop employee skills. What is ISO 17024 used for? ISO 17024 provides guidelines for certifying individuals. Organizations offering certification programs must meet its requirements for accreditation, covering the development of certification programs, candidate assessment, and certificate issuance. How do you build a skills management system for ISO? Start by identifying required skills based on relevant ISO standards, then assess what skills your workforce currently has. Determine the gaps between required and available skills, establish training to close those gaps, and implement a system to continuously track and update skills data. What are the five steps to ISO skills compliance? The five steps are: identify required employee skills based on ISO standards, assess available skills in your workforce, determine the gaps between required and current skills, establish training programs to close those gaps, and implement a skills management system to track ongoing compliance. Why is skills gap analysis critical for ISO compliance? Skills gap analysis reveals the difference between what your workforce can do and what ISO standards require. This gap determines the best growth path for employees and, in the case of ISO compliance, directly maps to meeting the standards during audits. What are the benefits of ISO certification? Benefits include improved customer satisfaction, increased operational efficiency, reduced costs, and a stronger competitive position. ISO-certified organizations are also more likely to win new customers and contracts because the certification signals quality and reliability. How does ISO 10018 relate to workforce competence? ISO 10018 provides guidance on engaging people in an organization's quality management system and enhancing their involvement and competence. It applies to any organization regardless of size, type, or activity, making it a broadly applicable standard for workforce development. Can a skills platform help maintain ISO compliance? Yes. A skills management platform simplifies tracking employee competencies against ISO requirements, managing skills gaps, directing employees to training, and maintaining auditable records. This ongoing monitoring is essential because ISO compliance is not a one-time event but an iterative, continuous process. How does training tracking support ISO audits? Tracking employee training progress creates the documented evidence auditors need to verify compliance. A robust skills management system provides auditable records of skills assessments, training completion, gap analysis, and ongoing development aligned to specific ISO standard requirements. What does ISO 14001 cover for skills management? ISO 14001 helps organizations improve environmental performance through efficient resource use, waste reduction, and sustainability. It requires organizations to ensure their workforce has the competencies needed to meet environmental management standards and objectives. --- ## Durable vs. Perishable Skillsets and Why It Is Important URL: https://skillsdb.com/blog/durable-vs-perishable-skillsets Why we should be talking about perishable skills vs. durable skills? Investing in the right balance of perishable and durable skill sets helps organizations outlast a volatile or fluctuating economy. With the global talent shortage becoming more and more apparent across all industries, the concept of durable and perishable skills has caught on. Employers around the world have started to recognize the learning needs for both types of skillsets. Though it can be tempting to focus on the skills needed right now, we should consider whether these skills will be as important in the future. We can't afford to tie our employees up with knowledge that will only be useful in a specific, narrow context, because the world is changing so quickly. Yet, current technological skills often meet the definition above. So, when developing a talent management program, a balance between perishable skills and durable skills must be created. What are Durable Skills? Durable skills are the skills that can be used in the future, making it possible to remain competitive even as your business landscape changes. Durable skills are not easily replaced by technology. Durable skills are a set of knowledge, experience, and abilities that will be needed in the future. They include things like creativity, critical thinking, and emotional intelligence. Durable skills will provide your employees with long-term benefits. These skills will not become obsolete because they are in demand everywhere. Many employee skills platforms now track the development and application of these long-lasting competencies to support continuous growth. Examples of durable skills include: Critical thinking and problem solving Public speaking Leadership Negotiation What are Perishable Skills? Perishable skills are skills that are relevant for a certain amount of time, and often contextual to a place or organization. They are not skills usable for the rest of your life. Skills like programming and web design are examples of perishable skills. Skills that have to do with specific technologies like blockchain technology or artificial intelligence will also be considered perishable skills. The term “perishable skill” was first used in the 1990s by futurist Alvin Toffler in his book “The Third Wave” to describe a skill that is no longer relevant in a society because it has been replaced by an innovation or new technology. Perishable skills are easily forgotten, outdated, or that no longer have a demand in the workforce. Some classic examples of perishable skills include: Using typewriters Using slide rules Punch cards Other perishable skills could include manual labor, manufacturing, and other jobs that can be replaced by automation. How Long Do These Skill Sets Last? According to Chief Learning Officer Magazine , skill durability can be divided into three categories: Perishable skills: Less than 2.5 years. These are specific technical skills that must be updated frequently. Semi-durable skills: 2.5 to 7.5 years. These tend to be frameworks that are based on an understanding that may remain relevant for a few years. Durable skills: More than 7.5 years. They are foundational to an employee's soft skill set. Creating the Right Balance of Perishable Skills vs. Durable Skills for Your Organization To close your organization’s skills gaps in the short-term, as well as for the future, determine which skills and competencies that are most needed fall into the categories of perishable skills and durable skills. Preferably, you will possess a versatile skills management tool like the SkillsDB that will help you label which groups your skills fall into. Additionally, integrating a skills management platform can help centralize and automate this process for better results. Next, create a process and schedule to review and, if required, modify the relevant skills and competencies within your competency model. Examine your perishable skills annually, at a minimum, and be certain your competency model – as well as your employee’s skillsets – remain fresh and pertinent. Then, make sure your learning and development platforms and individual development plans align, using the skills your organization actually requires now, as well as for the future. In Conclusion It may sound like a drastic change, but if you've been relying on the existing talents of your team to sustain the competitiveness of your organization, this idea may come as a rude shock. In 3 years, your company will have significantly less capacity to adapt to a changing marketplace. On the other hand, if you encourage employees to develop skills by adapting, learning, and growing, they'll have a more diverse and relevant skillset for decades to come. FAQ What are durable skills in the workplace? Durable skills are competencies that remain relevant for more than 7.5 years and resist obsolescence. They include critical thinking, leadership, emotional intelligence, and problem-solving — abilities that technology cannot easily replace. What are perishable skills and how long do they last? Perishable skills are technical or context-specific competencies that become outdated within 2.5 years. Examples include specific programming languages, software tools, and technology-dependent capabilities that must be continuously refreshed. Why should organizations balance perishable and durable skills? Focusing only on immediate technical needs leaves organizations vulnerable when those skills become obsolete. A balanced approach ensures employees can adapt to market shifts while maintaining the foundational competencies that drive long-term performance. What are examples of durable skills? Common durable skills include critical thinking, public speaking, leadership, negotiation, and emotional intelligence. These competencies transfer across roles and industries, making them valuable throughout an entire career. How often should perishable skills be reviewed? Organizations should examine perishable skills at least annually to ensure their competency models remain current. Regular reviews help keep employee development plans aligned with actual business needs and evolving market demands. What are semi-durable skills? Semi-durable skills last between 2.5 and 7.5 years. They typically involve frameworks or methodologies built on foundational understanding that remains relevant for several years before requiring significant updates. How does SkillsDB help manage skill durability? SkillsDB lets organizations label and categorize skills by durability type — perishable, semi-durable, or durable. This makes it easier to schedule reviews, align development plans, and ensure your competency model stays relevant. Can perishable skills become obsolete overnight? While not overnight, perishable skills can lose relevance rapidly when new technologies emerge. Historical examples include typewriter proficiency and punch-card operation — once essential, now entirely irrelevant. How do durable skills protect against workforce disruption? Employees with strong durable skills adapt more readily to changing roles and technologies. Because these competencies transfer across contexts, they provide a foundation for continuous learning and long-term career resilience. What role do learning plans play in skill durability? Individual development plans should align with both current technical needs and long-term durable skill growth. A structured learning plan ensures employees build a diverse skillset that remains relevant for decades, not just the next project cycle. --- ## Why is Skills-Based Management Crucial Today? URL: https://skillsdb.com/blog/why-skills-based-management-is-absolutely-critical-in-the-working-world-of-today Many companies have started to use skills-based management in order to fill the demand for skilled workers. See why this is crucial. The talent gap is a phenomenon in which the demand for skilled workers exceeds the supply of qualified applicants. This imbalance can lead to a higher cost of labor, increased wages, and increased employee turnover. The talent gap is an issue that has been affecting organizations for years and has only grown more dire in recent times. It’s not only about a lack of skilled workers, but also about the lack of qualified applicants for the jobs available. Many companies have started to use skills-based management in order to narrow this gap. They try to find people with the necessary skills and train them on what they don’t know. This approach creates a training needs analysis at both the employee and corporate levels. A skills management platform can support this effort by helping organizations map current capabilities and identify development areas. The skills gap is caused by the need for specialized skills that are not taught in schools or colleges. It is also caused by employers who are unwilling to train their employees and instead hire new ones with more appropriate skills. In order to address this issue, employers should invest more in training employees. They should also consider re-training current employees who have skills that may be obsolete or no longer needed in the workplace. Employee skills platforms can help streamline this process by offering insights into individual and team skill profiles. The Issue with Traditional Management Practices In years past, managers were mainly concerned with the production of goods and services. They were responsible for the development and implementation of policies and procedures. In recent years, traditional management practices have been criticized because they are not suitable for modern management needs. Traditional management practices have led to micromanaging which is a problem in many organizations today. Micromanaging can lead to lower productivity, more stress in the workplace, and lower employee morale. It also leads to a feeling of powerlessness among employees because they feel that their opinions are not valued or heard. It is important for managers to change their mindset from being focused on production to focusing on people’s needs so that they can create an environment where people can be productive and happy at work. The Benefits of Skills-Based Management Skills-based management is an approach focusing on people’s skills and abilities. It emphasizes the importance of employees having the skills and abilities needed to do their work well. The benefits of skills-based management are: The organization is more likely to have a sustainable competitive advantage. Employees feel more fulfilled by their jobs. Employees are more engaged in their work. There is less turnover because employees are happy with their jobs. Furthermore, skills-based management is a form of leadership where the leader focuses on the skills, competencies, and needs of his team members and helps them develop in their strengths. This type of leadership is a great way to make your employees feel valued, respected, and appreciated. It also helps you identify skills gaps. It can be filled by hiring new employees or training existing employees to fill those gaps. A skills-based organization leverages these principles to create agile, future-ready teams. Conclusion and Closing Thoughts In a skills-based management system, employees are measured based on their skills and knowledge. This allows them to work in their strongest areas and receive support for their weaker ones. Some companies are using this system to assign employees with different skillsets to different tasks. This way they are able to use their resources in the best possible way and make sure that they don’t waste time on tasks that they are not best at. In conclusion, skills-based management is a way of optimizing the work environment and making sure that employees are using their skills in the best way possible. It is also a way of increasing employee satisfaction and productivity. FAQ What is skills-based management? Skills-based management is a leadership approach that focuses on employees' skills and abilities rather than job titles or tenure. It measures people based on what they can do, then assigns work accordingly to maximize both performance and satisfaction. How does the talent gap affect organizations? The talent gap occurs when demand for skilled workers exceeds the supply of qualified candidates. It drives up labor costs, increases wages, accelerates employee turnover, and limits an organization's ability to execute on strategic goals. Why are traditional management practices failing today? Traditional management focuses on production and process control, which often leads to micromanagement. This approach reduces productivity, increases workplace stress, and lowers morale — the opposite of what modern knowledge workers need to thrive. What are the benefits of skills-based management? Organizations gain a sustainable competitive advantage, higher employee engagement, greater job satisfaction, and reduced turnover. Employees feel more valued because their strengths are recognized and developed, not just their output measured. How does skills-based management reduce employee turnover? When employees work in areas that match their strengths and receive support for growth areas, job satisfaction increases significantly. People stay longer at organizations where they feel their skills are recognized and developed. What causes the skills gap in organizations? The skills gap stems from specialized skills not being taught in formal education and employers who hire externally rather than training existing staff. Rapid technological change compounds the problem by making current skills obsolete faster than ever. How can a skills management platform help? A skills management platform like SkillsDB maps current capabilities across your workforce and identifies development gaps. This gives you visibility into who has what skills, where gaps exist, and how to close them through targeted training. Should employers retrain or hire to close skills gaps? Retraining existing employees is typically more cost-effective and faster than external hiring. It also preserves institutional knowledge and boosts retention, since employees value organizations that invest in their professional development. How does skills-based management improve employee engagement? By aligning work assignments with individual strengths, employees feel more competent and fulfilled. When people understand how their skills contribute to organizational goals, they are more engaged and productive in their roles. What is a training needs analysis? A training needs analysis identifies the gap between current employee skills and the skills required for success. It operates at both individual and organizational levels, creating a roadmap for targeted development that addresses real business needs. --- ## Why You Need Employee Learning Ecosystems and How to Build One URL: https://skillsdb.com/blog/why-you-need-employee-learning-ecosystems-and-how-to-build-one Employee learning ecosystems allow companies to provide an effective and efficient learning experience for their employees. Technology has given us access to more information at our fingertips than ever before. We have the ability to engage with this information in ways that are both efficient and effective. It’s critical that we take advantage of the tools and channels available to us. That will enable us to create an efficient and effective learning experience. Scaling a learning strategy is often difficult and requires a thoughtful approach. It’s important to include all of the necessary components that will create a well-defined strategy that turns into an efficient and effective learning experience for everyone involved. This is where a learning and development platform can support structured planning and delivery. Why Are Employee Learning Ecosystems Important? Employee learning ecosystems allow companies to provide an effective and efficient learning experience for their employees. By focusing on the needs of both the employee and employer, it’s possible to build a learning experience that becomes an integral part of an organization’s culture. The traditional education-learning paradigm focuses on the individual. We are now in an era where everyone has access to information at their fingertips. Thus, companies need to focus on providing their employees with an enriching learning experience. Of course, it will benefit both them and the company. In order to have a scalable learning strategy, it’s important to first understand what your employees need and the types of tools and channels they use. Implementing a competency based learning platform helps align learning objectives with employee roles, ensuring targeted skill development. The learning experience shouldn’t stop when an employee leaves the office. In fact, it should follow them into their personal lives. This is why it’s critical to make sure you have learning tools and channels that both educate and entertain your employees outside of the workplace. It’s important to identify what your employees need and the types of tools and channels they use in order to provide them with the information they need most. Above all, it’s important to have an objective when developing your learning strategy. It’s critical to ensure your strategy is balanced with both company and employee-focused objectives. The end result will be an effective learning experience that scales across employees, who are expected to take on new roles and responsibilities. This is why it’s important to have a learning strategy that can adapt to your employees’ needs. Benefits of Learning Ecosystems The most effective learning ecosystems are flexible and can adapt to evolving business needs, new employees, and changing technologies. This is why it’s important to have a learning strategy that is adaptable and scalable. It should focus on the needs of your employees. Plus, it should provide them with opportunities to learn in ways that are interesting, helpful, and easy to understand. Keeping employees engaged with a learning strategy is just as important as developing one. A well-defined learning ecosystem will create an efficient and effective learning experience for everyone involved. It’s important to focus on the needs of your employees and provide them with an experience that is both scalable and relevant. It will allow them to take on new roles and responsibilities as they evolve within the company. Your employees are your greatest asset. That’s why it’s important that you provide them with the tools and channels necessary to succeed. By having a learning strategy that is both balanced and scalable, it’s possible to create a culture that values education and growth . This will help your employees take on new roles and learn new skills. Plus, it will help them adapt to an ever-changing business landscape. FAQ What is an employee learning ecosystem? An employee learning ecosystem is an integrated network of tools, channels, and content that delivers continuous learning experiences. It goes beyond one-off training sessions to create a culture where learning is embedded in daily work. Why are learning ecosystems important for organizations? They ensure employees can develop skills that keep pace with changing business needs. A well-designed ecosystem makes learning scalable, relevant, and efficient — benefiting both individual career growth and organizational performance. How do you build a scalable learning strategy? Start by understanding what your employees need and the tools they already use. Then design a balanced strategy with both company-focused and employee-focused objectives that can adapt as roles and responsibilities evolve. What makes a learning ecosystem effective? The most effective ecosystems are flexible and adapt to new employees, evolving business needs, and changing technologies. They provide learning opportunities that are interesting, relevant, and easy to understand across the entire workforce. Should learning extend beyond the workplace? Yes. The most impactful learning strategies follow employees into their personal lives through accessible tools and channels. When learning is convenient and engaging outside the office, it becomes part of an employee's identity — not just a work obligation. How do learning ecosystems improve employee retention? When employees have clear paths to develop new skills and take on new responsibilities, they are more likely to stay. A culture that values education and growth creates loyalty and reduces the cost of external hiring. What tools are needed for a learning ecosystem? You need a mix of content delivery platforms, collaboration tools, and tracking systems. A competency-based learning platform like SkillsDB helps align learning objectives with specific roles, ensuring development stays targeted and measurable. How do you keep employees engaged with learning? Provide diverse learning formats, make content relevant to their roles, and show clear connections between skill development and career advancement. Engagement requires learning to feel valuable — not like a compliance checkbox. What is the difference between training and a learning ecosystem? Training is typically a one-time event focused on specific knowledge transfer. A learning ecosystem is an ongoing environment that supports continuous development through multiple channels, formats, and feedback loops. How do you measure learning ecosystem success? Track skill development over time, employee engagement with learning resources, internal mobility rates, and retention metrics. The best ecosystems show measurable improvements in both employee capabilities and business outcomes. --- ## Why are Digital Learning Strategies Crucial for Success? URL: https://skillsdb.com/blog/digital-learning-strategies Digital learning strategies combine technology, content and data that empower employees to learn more effectively. Find out more. Digital Learning Strategies Digital learning strategies, through the advancement of technology, content, and data have made it possible for us to finally have access to the information we need, when and where we need it. Thus, creating the perfect ecosystem for continuous employee learning and growth. Technology is the backbone of learning in today’s digital era. That is because it provides us with access to resources outside of our physical location. This means that learning is not confined to the walls of an organization, which has greatly enhanced the collaboration between employees that works towards increasing knowledge and skills. Modern learning and development platforms are enhancing digital learning strategies by enabling real-time tracking, personalized content delivery, and collaborative tools. These platforms ensure that employees stay aligned with the organization’s goals while developing key competencies. But, even though technology is an important component of any learning strategy, it’s just one piece of the puzzle. Digital learning strategies without a solid content or data foundation will ultimately fall short of producing the results an organization is looking for. Why Is Content So Important? Content has always been a vital component of digital learning. However, with the many different sources available to us today, sourcing the right content has become increasingly challenging. The content that employees use should be relevant, accurate, and pertinent to the educational topic at hand. Even though the content is important, it’s still not enough on its own. Without data that can provide insights into what content is most relevant and what learning strategies are working, organizations can’t properly track their digital learning initiatives. The right combination of technology, content, and data can be a powerful learning strategy. Furthermore, it can empower employees to learn more efficiently and effectively. The availability of technology is expanding the way we approach digital learning strategies. Employees are no longer limited to the resources in their personal ecosystem. They can now leverage resources through their organization’s ecosystem, which allows them to learn collaboratively and expand their knowledge. Today’s Technology Impact Technology’s continuous improvement is also making it possible for global-scale ecosystems where you can access content from anywhere in the world. Digital learning strategies are also increasing, giving employees access to various educational topics. All of this can expand their skills and knowledge beyond what they would learn in the classroom. Because of technology’s ever-growing data component, employees can track their own learning and development and focus on what works and what doesn’t. This allows organizations to audit and certify their employees’ skills and knowledge. Of course, this is important for hiring and onboarding new members. A well-structured competency based learning platform can help streamline this process by aligning skill development with specific job roles and performance metrics. Digital learning strategies allow organizations to focus on what matters. And, that is creating a culture that embraces learning and growth both inside and outside of the classroom. Digital learning strategies allow employees to approach learning in their own way, which is creating a culture of continuous learning and development . It’s allowing employees to learn from each other and continuously level up their skills. And, ultimately, it’s helping organizations empower their people to do more, be more, and learn more. The digital era has created a world where we can all be lifelong learners. Ultimately, it’s up to us to take advantage of this beneficial ecosystem. It’s time to embrace technology and make learning efficient, collaborative, effective, and accessible, which is the only way we’ll be able to keep up with this ever-growing environment. FAQ What is a digital learning strategy? A digital learning strategy combines technology, content, and data to create continuous learning experiences for employees. It leverages digital tools to make learning accessible anywhere, anytime — not confined to a classroom or office. What are the three pillars of digital learning? Technology, content, and data form the foundation. Technology provides access and delivery, content delivers the knowledge, and data provides insights into what is working and where to improve. Why is content critical in digital learning strategies? Without relevant, accurate content, even the best technology falls flat. Content must be pertinent to the educational topic and curated carefully, since the proliferation of digital sources makes finding quality material increasingly challenging. How does data improve digital learning outcomes? Data lets organizations track which learning strategies work and which content resonates most. Employees can monitor their own development, while leaders can audit and certify workforce skills — making learning measurable, not just aspirational. How does technology expand learning beyond the classroom? Technology removes physical location barriers, enabling employees to access learning resources from anywhere in the world. This fosters collaboration across teams and geographies, expanding skill development beyond what any single classroom could deliver. What role does a competency-based learning platform play? A competency-based learning platform like SkillsDB aligns skill development with specific job roles and performance metrics. It streamlines the process of tracking progress, delivering personalized content, and ensuring employees stay aligned with organizational goals. How do digital learning strategies support continuous development? They let employees approach learning at their own pace and in their preferred format. This creates a culture of continuous development where people learn from each other and progressively build skills over time. Can digital learning strategies help with employee onboarding? Yes. Digital strategies allow organizations to audit and certify employee skills and knowledge during onboarding. New hires can access structured learning paths immediately, reducing time-to-productivity and ensuring consistent knowledge transfer. What makes a digital learning strategy fail? Strategies fail when they rely on technology alone without solid content or data foundations. Without relevant material and measurable insights, organizations cannot track effectiveness or ensure learning produces real business results. How does digital learning create a culture of growth? When employees have consistent access to learning tools that are efficient, collaborative, and accessible, learning becomes part of how work gets done. This cultural shift helps organizations empower their people to continuously level up. --- ## Upskilling Technologies— Meeting Tomorrow's Skill Demands Today URL: https://skillsdb.com/blog/upskilling-technologies-meeting-tomorrows-skills-demands-today Meeting tomorrow's skills demands today. 375 million workers will have to learn new skills by 2030 to stay relevant. With the rise of new upskilling software platforms, workplace skill needs are shifting rapidly. People will need to both upgrade their skills and acquire new ones to stay relevant in their careers. Companies will have to reskill and upskill their existing workforces to address these changing needs and will also need to tap new talent pools, including younger workers and reskilling initiatives. Implementing an effective upskilling program for employees is now a strategic priority across all industries. Welcome to the 3rd part in our 3 part Upskilling Series. 1. Defining the Skills of Tomorrow: Reskilling and Upskilling , 2. Defining the Skills of Tomorrow: What Are They and What Makes Them Important? According to the McKinsey Global Institute , 375 million workers will have to learn new skills by 2030 in order to stay relevant in the job market. Reskilling and upskilling are not new. In a changing economy, workers have always had to learn or relearn how to do their jobs or acquire tools that enable them to perform differently. However, the pace of change across all industries is accelerating and has been affecting even blue-collar work. Thus, many workers feel they can no longer rely on their existing skills and knowledge to take them as far as they would like, creating a sense of urgency around reskilling. Companies and organizations play an important role in helping their workers reskill. In fact, the responsibility to reskill and upskill should not necessarily fall solely on the employee as businesses have a significant role to play by providing reskilling opportunities. Leveraging a robust upskilling and reskilling platform can help companies scale learning initiatives, track progress, and deliver tailored content to meet diverse employee needs. Not only do they need to develop the skills of their existing workers but also offer to retrain new employees who bring different skill sets or perspectives from their previous employment or educational experiences. Metrics, Measurements & Impact of Upskilling Technologies One of the ways to raise awareness about the need for skill development is to put a higher value on creating metrics that illustrate how skill development can assist or what will happen if the issue isn’t addressed. One should be able to look at their own organization and how it impacts business processes, customer experiences, or even what new products or services they are launching. Organizations have to be willing to put a metric system in place that will allow them to measure the impact of skills development. Adopting an upskilling platform that integrates with HR systems can streamline this process and offer real-time analytics. For instance, to measure the effectiveness of a reskilling and upskilling program, these metrics can be used. Skill Identification As an employer, you should have a clear idea of each worker’s skills and what they can do beyond their job title. This will allow you to identify which workers need reskilling and upskilling to be successful in their current role as well as the future of your business. Cost Avoidance Hiring someone from outside may be significantly more expensive than training employees for a role . Unfortunately, many organizations do not factor in the cost of salary and other expenses that come with a new hire. On the other hand, training employees is much less expensive and can be spread over a longer time, providing the organization with more value at the same cost. Depending on their role, some workers may also have skills that are transferable to other parts of your business, allowing you to retain them even if they are unable to do their current job for some reason. Business readiness By closely cooperating with the sales and operations leaders, you can easily identify the skillset needed to cater to your customers’ needs and wants. Then, you can take a look at the current employee skills database to make sure your workforce possesses the necessary skills to deliver on those needs. Once you have completed the analysis, you can create a plan for reskilling and upskilling your workforce and embed it into your yearly business goals. Conclusion It is essential for businesses, individuals, and society to pay attention to the need for reskilling and upskilling. This will require constant assessment of training needs, commitment from organizations to provide training opportunities, as well as a willingness of workers to continue learning. Keeping up with changes in upskilling technologies and your industry is not only necessary for survival but it is also the only way to take your business or career to the next level. FAQ How many workers need new skills by 2030? According to the McKinsey Global Institute, 375 million workers worldwide will need to learn new skills by 2030 to stay relevant. This makes reskilling and upskilling a strategic priority, not a nice-to-have. What are upskilling technologies? Upskilling technologies are platforms and tools that help organizations deliver, track, and measure employee skill development at scale. They include learning management systems, skills intelligence platforms, and integrated HR analytics tools. Why is upskilling a strategic business priority? The pace of change across all industries is accelerating, making existing skills obsolete faster than ever. Companies that invest in upskilling retain talent, reduce hiring costs, and maintain the workforce capabilities needed to compete. How do you measure the impact of upskilling programs? Effective measurement includes skill identification, cost avoidance compared to external hiring, and business readiness assessments. An upskilling platform that integrates with HR systems can provide real-time analytics on all three dimensions. Is upskilling more cost-effective than hiring externally? Yes. Hiring from outside is significantly more expensive when you factor in salary, onboarding, and ramp-up costs. Training existing employees costs less, preserves institutional knowledge, and can be spread over a longer timeline. What is skill identification and why does it matter? Skill identification means mapping each worker's capabilities beyond their job title. It reveals who needs reskilling, who is ready for new roles, and where your workforce has gaps — the foundation for any effective upskilling strategy. What role do employers play in reskilling workers? Employers bear significant responsibility for reskilling, not just employees. Companies need to provide training opportunities, retrain new hires who bring different skill sets, and create structured programs that align with business goals. How does business readiness relate to upskilling? By working with sales and operations leaders to identify the skills needed for customer success, you can compare those needs against your current workforce. The gap between the two defines your upskilling roadmap. What metrics should track upskilling program effectiveness? Key metrics include skill acquisition rates, cost savings versus external hiring, business readiness scores, and employee retention improvements. These should be embedded in yearly business goals alongside revenue and operational targets. How does SkillsDB support upskilling initiatives? SkillsDB serves as an upskilling and reskilling platform that helps companies scale learning initiatives, track individual progress, and deliver tailored content. It integrates with HR systems to provide real-time analytics on workforce skill development. --- ## Defining the Skills of Tomorrow: Reskilling and Upskilling URL: https://skillsdb.com/blog/reskilling-and-upskilling With the pace of change in today's world, future-proofing learning programs while reskilling and upskilling your workforce is imperative. What is reskilling and upskilling? It is no secret that technology has already transformed the workforce. In fact, we might not have all the skills we need but we have to be willing to focus more on improving our competencies . Many workers must use software in order to do their jobs, but rarely receive training on how to use it effectively. This skill gap highlights the urgent need for a well-structured upskilling program for employees. Employees often struggle with even the most basic computer tasks. Yet they are expected to complete complex activities using that software. Employers must recognize the role of technology in creating this disconnect between workers and their jobs. While many employees are anxious to learn new skills, they do not have access to the training required for success. This is where an upskilling and reskilling platform becomes essential—providing structured learning paths that support career growth and prepare teams for future demands. While some businesses truly embrace reskilling and upskilling initiatives, others take a more passive stance towards future-proofing their workforce. For example, companies may invest in learning and development initiatives that only serve their immediate needs. Such programs focus on the present state of affairs. Thus, do little to prepare workers for a future where new skills will be necessary. In some cases, reskilling is not even an option; many employers downsize or automate jobs specifically because they do not see the value in continuing operations. Others may be unable or unwilling to invest in employees, making it difficult for them to take advantage of future-proofing opportunities. Learning and development initiatives must address these issues to truly make a difference. Taking a Strategic Approach As new technologies are developed. Organizations must realize that these machines are not just tools to be used on the job. They are intelligent systems that need training and constant care. Even though current technology has made some jobs easier or eliminated them altogether, it also has created new opportunities for businesses of all sizes around the world. This is why it is crucial to focus on upskilling and reskilling to ensure the future workforce is equipped with the skills needed for tomorrow’s world. While technology has made certain jobs obsolete, it has also made it possible for people to pursue different careers or take more interesting positions within their company or industry. For example, computers have automated many of the administrative tasks workers used to perform, which has freed them to take on more creative or strategic responsibilities. Workers must be willing to modify their skill sets in the face of technological advances in order to maximize their value in today’s labor market. Managing Stakeholders Managing stakeholders may make or break any learning project, but when it comes to reskilling or upskilling, the stakes are higher. As the global economy continues to shift, companies are forced to adapt their long-term training strategies for existing employees. Organizations must design programs that meet several objectives at once: using technology to enhance employee capabilities while also meeting the demands of stakeholders. Given the pace of change in today’s business environment, future-proofing learning programs require more than just an emphasis on emerging technology. Employers need to ensure that workers have access to comprehensive career development programs, which help them understand what they do well and how their skills can add value in a new capacity. While many employees are eager for opportunities to try something new, others may require more time and guidance than can be provided through a casual conversation. Conclusion Today, as technology and automation increasingly shape the global economy, it is crucial for everyone to acquire the skills needed to remain competitive in an ever-changing world. Workers must be willing to modify their skill sets in order to maximize their value within the labor market. Employers need to ensure workers have access to comprehensive career development programs and employees themselves must strive to keep learning new skillsets. FAQ What is the difference between reskilling and upskilling? Upskilling upgrades existing skills so employees can excel in their current roles. Reskilling trains employees for entirely new roles, often because their current position has been automated or eliminated. Both are essential for workforce resilience. Why is future-proofing your workforce important? Technology and automation are reshaping every industry at an accelerating pace. Organizations that fail to future-proof their learning programs risk having a workforce with outdated skills, leading to lost competitiveness and higher turnover. How does technology create skills gaps in organizations? Many workers must use software to do their jobs but rarely receive formal training on it. This disconnect between required tools and actual competency creates a growing gap that only structured reskilling and upskilling programs can close. Why do some companies fail at reskilling initiatives? Some organizations invest only in learning that serves immediate needs, doing little to prepare workers for future demands. Others are unwilling to invest in employee development at all, choosing instead to downsize or automate roles. How should organizations approach reskilling strategically? Recognize that new technologies are intelligent systems requiring ongoing training and care. Combine technology adoption with comprehensive career development programs that help employees understand their strengths and how to add value in new capacities. What role do stakeholders play in reskilling programs? Stakeholder management can make or break any reskilling initiative. Programs must meet multiple objectives simultaneously — enhancing employee capabilities through technology while satisfying leadership expectations for measurable business outcomes. How has automation changed career development? Automation has eliminated some roles but created new opportunities. By automating administrative tasks, workers are freed for more creative and strategic responsibilities. The key is willingness to modify skill sets as technology evolves. What does a comprehensive career development program include? It helps employees understand what they do well, identifies how their skills add value in new capacities, and provides structured learning paths. It goes beyond casual conversations to deliver guided, measurable development over time. Who is responsible for employee reskilling? Responsibility is shared. Employers need to provide access to comprehensive development programs and training opportunities. Employees must be willing to learn and modify their skill sets to maximize their value in a changing labor market. How can an upskilling platform help with reskilling? An upskilling and reskilling platform provides structured learning paths, tracks progress, and delivers tailored content. It helps organizations scale their initiatives while giving employees a clear roadmap for career growth and skill development. --- ## Defining the Skills of Tomorrow: What Are They? URL: https://skillsdb.com/blog/defining-the-skills-of-tomorrow-what-are-they-and-what-makes-them-important It’s important for individuals and businesses to stay ahead and learn how defining the skills of tomorrow can help them in the future. As technology rapidly changes and develops, so too does the skill set that many jobs require. What it takes to be successful in the workforce today may be vastly different from what is needed tomorrow. It’s important for both individuals and businesses to stay ahead of the curve and learn how defining the skills of tomorrow can help them in the future. Recruiters and employers can sometimes struggle to find enough skilled workers. That’s why it’s important to try to anticipate labor market needs. What may be in high demand now could change next year or even next month. However, there are certain skills that are likely to remain important in the future. Skills that are transferable across occupations, have a high value to employers, or are in demand for emerging fields will be useful not just now but later on as well. Upskilling and Reskilling Defined Upskilling and reskilling are two terms that describe acquiring new skills for the workforce. In fact, upskilling usually refers to upgrading the skills of current employees. On the other hand, reskilling usually means training new employees for specific roles. Both approaches are important for businesses as they try to stay ahead of the curve and ensure that their workforce has the skills to perform their jobs well. Many companies use an upskilling and reskilling platform to streamline these training efforts and deliver effective learning experiences. Upskilling When it comes to upskilling, current employees are usually encouraged to further their education or accomplishments. This could mean gaining more formal education, training with skills that are directly related to the job they currently do, or even taking on side work that helps them develop additional skill sets outside of what is required for their jobs. There are a few reasons why why an upskilling program for employees is such an important development for businesses. First, it helps to ensure that employees have the skills they need to do their jobs well. Second, it allows employees to keep up with changes in technology and the marketplace and stay current on new developments. And finally, it can help businesses attract and retain new talent by being perceived as an employer of choice. Employee training is a cost for businesses. But it can help to cut costs in the long term by reducing the likelihood of turnover and supporting employees in doing their jobs well. The success of a business relies on its workforce. So, providing opportunities through an upskilling platform is an important factor when it comes to maintaining a competitive edge. Reskilling When it comes to reskilling, businesses often face the challenge of needing employees with specific skills for particular roles. This can be difficult when the workforce doesn’t have the exact skill set that’s needed or when there is a shortage of workers with those skills. In these cases, businesses may need to look into training their employees for the specific roles that they need to fill. Reskilling can be an important way for businesses to start defining the skills of tomorrow in the labor market and ensure that they have the workers they need to succeed. It can also help businesses to fill in any skill gaps that may exist in their workforce. But reskilling doesn’t always take place within businesses themselves. Many organizations are working to develop reskilling programs, which can allow workers to both pick up new skills and gain access to education opportunities without requiring them or their employers to make a major commitment. Determining the Skills to Target When it comes to upskilling and reskilling, it’s important for businesses to determine which skills they should target. This can be difficult, as the needs of businesses can vary widely and the skills that are in demand can change quickly. However, there are a few factors that can help to guide this decision-making process. One way to identify skills that are in demand is by talking with employers. They can provide insight into which skills they need the most and may be open to sharing what makes these roles difficult to fill. Another option is looking at labor market forecasts, which can help businesses understand where the economy is headed and how it’s changing over time. This information can be helpful in defining the skills of tomorrow and identifying which skills may be in high demand in the future. Businesses also need to take into account their own needs and what they’re hoping to accomplish with upskilling and reskilling. For example, if a business is looking to expand into new markets, they may need employees with different skills than they currently have. In this case, upskilling and reskilling may be focused on developing new skill sets that are specific to the industry or market that the business is targeting. Training Methods: Hard vs. Soft Skills There are two main approaches to reskilling and upskilling: hard skills training and soft skills development. Hard (or Technical) Skills Many of the formal education programs available for upskilling or reskilling focus on technical capabilities. These are sometimes referred to as “hard” or "technical" skills because they can be easily defined, measured, and often taught in a formal educational setting. Hard skills are often specific to certain roles or industries and can be more difficult to learn on the job. Some examples of hard skills include: Forensic accounting Next.js software engineering Mechanical engineering Soft Skills Alternatively, soft skills are interpersonal or “people” skills that are critical for success in any role. They include things like communication, problem-solving, and critical thinking. Soft skills are often more difficult to quantify or measure, but they’re essential for a productive and successful workplace. Some examples of soft skills include: Leadership Teamwork Time management Public speaking Critical thinking Both hard and soft skills can be challenging to develop without formal education programs. Some jobs, such as jobs in the IT and healthcare fields, require a certain set of hard skills. In these cases, upskilling or reskilling will focus specifically on developing those technical capabilities. But other jobs may rely more heavily on soft skills, such as interpersonal skills or creative thinking. In these cases, soft skills training may be more important. Regardless of the focus, businesses should make sure that their employees have the opportunity to develop both hard and soft skills. Hard skills are essential for specific roles within a company, while soft skills are important for team productivity and overall success. Defining the Skills of Tomorrow Though hard skills can be learned through traditional methods, soft skills are more difficult to teach in a classroom setting. That said, there are a few methods that can be used to help employees develop their soft skills and start defining the skills of tomorrow. One way is to provide employees with opportunities to practice their skills in a real-world setting. Another way to help employees develop their soft skills is through providing them with feedback and coaching. FAQ What are the skills of tomorrow? The skills of tomorrow are competencies that will remain in demand as technology and markets evolve. They include both technical capabilities for emerging fields and transferable soft skills like leadership, critical thinking, and communication. What is the difference between upskilling and reskilling? Upskilling means upgrading the skills of current employees to keep them effective in their existing roles. Reskilling means training employees for entirely new roles when their current position changes or is eliminated. Why is upskilling important for employee retention? Upskilling helps businesses attract and retain talent by demonstrating investment in employee growth. When employees see opportunities to develop and advance, they are more likely to stay and contribute at a higher level. What are hard skills versus soft skills? Hard skills are specific, measurable technical abilities tied to particular roles — like accounting or software engineering. Soft skills are interpersonal competencies like teamwork, communication, and critical thinking that apply across all roles and industries. How do organizations determine which skills to develop? Talk with employers about in-demand skills, review labor market forecasts, and assess your own business strategy. If you are expanding into new markets, you may need entirely different competencies than your workforce currently possesses. Why do businesses need both hard and soft skills? Hard skills are essential for specific technical roles, while soft skills drive team productivity and collaboration. A workforce that is technically capable but lacks communication or problem-solving skills will underperform. How can businesses identify future skill demands? Use labor market forecasts to understand where the economy is heading. Combine that with employer insights about hard-to-fill roles and your own strategic plans to build a forward-looking skills roadmap. What role does reskilling play in the labor market? Reskilling helps businesses fill skill gaps when the workforce lacks needed competencies or when there is a shortage of qualified workers. It also gives employees access to education and career opportunities without requiring a major upfront commitment. How do you develop soft skills in employees? Provide opportunities to practice in real-world settings and deliver regular feedback and coaching. Unlike hard skills, soft skills are difficult to teach in a classroom — they develop best through experience and guided reflection. What skills are transferable across industries? Leadership, teamwork, time management, public speaking, and critical thinking transfer across virtually any role or industry. These competencies remain valuable regardless of how technology or market conditions change. How does an upskilling platform support skill development? An upskilling platform like SkillsDB streamlines training delivery, tracks employee progress, and helps organizations identify which skills to target. It supports both hard and soft skill development with structured, measurable learning paths. --- ## On-the-Job Training: A Quick Guide to Methods and Tools URL: https://skillsdb.com/blog/on-the-job-training-methods-and-tools Looking for ways to leverage on-the-job training? There are several methods and tools that can help you get your employees up-to-speed quickly. Introduction: What is On-The-Job Training? Nowadays, organizations need to be more innovative and agile in order to stand out. In this digital age, the talent management process is a key factor that can help a company be agile and competitive. On-the-job training is an essential part of any business. It is the one thing that can make or break a company’s growth and survival. An on the job training program with a low cost, low effort and high return on investment is what every company strives for. On-the-job training is often referred to as “Training on the Job” or “OJT.” OJT refers to training that takes place on the job site shown in the 3 methods below. OJT comes in two flavors: Formal and Informal. Formal training is set up during work hours and doesn’t take away from the employee’s job time. While Informal training happens during work hours but with permission from the employer. In this article we will be talking about formal on-the-job training. A robust training platform for employees can streamline on-the-job training, making it easier to deliver consistent, trackable, and engaging learning experiences across teams What are the Best Formal Methods? Mentoring In today’s workplace, there are lots of ways of achieving on the job training. Mentoring is one of the most popular methods of on the job training that continues to grow in popularity each year. Many companies look to mentor employees because this ensures they are able to retain valuable talent. Mentoring is most often done through one-on-one coaching sessions with the mentee. Mentors provide advice, guidance, and connections that can help the mentee grow professionally. Mentors are experienced professionals who are experts in a certain part of their job and offer their services to guide beginners or less experienced employees through real-life working conditions (on the job training). Online Courses Training courses are another platform for on the job training where learners can get instant access to lectures and instructional content online with video tutorials, demonstrations, quizzes, etc. An online employee training platform can support these efforts by giving employees a central place to access learning materials anytime. Online courses and resources are a great way for employees to upskill and stay current with new trends in their industry. These courses can help employees find new inspirations, learn new skills, and keep up with the latest developments in the field. Project Experience Putting an employee on a project for a specified period of time with specific tasks can be a great way for them to gain on the job training. If you want to teach your employees the basics of a new job but you don’t have the time then project-based learning may be the solution. Project-based learning is when you give an employee specific tasks to complete in a specified period of time. The employee will learn not only the tasks but also the necessary skills to complete them. What are the Best Software Tools to Manage OJT? Once your employee has started their training program the question becomes what is the best way to track it and report on it. Eventually you'll want to look at the ROI stemming from your training programs. First, we will discount using spreadsheets for tracking training. The issue here is that inevitably multiple spreadsheets will start showing up in your company all representing the same data, without the ability to do any company wide or consolidation of the data. If you are a very small company though spreadsheets could be an answer for you. Project Management A research study found that 83% of employees know their company’s goals, 54% know what they need to do to achieve those goals, but only 16% are actually doing those tasks. Project management software can help companies track and assign the right tasks to the right people at the right time. If your primary method of OJT is project oriented then you can go back at anytime and see which OJT tasks the employees have completed on the project. The downside to this methodology is that it is hard to measure the ROI of the effectiveness of this method because there is no beginning skill level and ending skill level to compare. Training Tracking Tracking software for on-the-job training can be a great way to keep track of what employees are learning and how they are progressing. This is especially true for employees that have been on the job with the company for many years and may not be able to remember what they were taught in training or at any time in their career. If your primary method of OJT is online courses then you can track all courses taken by an employee and provide consolidated reporting for your company. The downside to this methodology is that it is hard to measure the ROI for the effectiveness of the project management method because there is no beginning skill level and ending skill level to compare. Talent Management (with integrated tracking) Training is the backbone of any company’s talent management. Talent Management Software shows the starting point of an employees skill level, and an ending point to an employees skill level. These skill gap measure the success rate of your OJT program. Combine skill gap analysis with training tracking, and the software solution reduces costs and increases efficiency, while at the same time increasing training success rates. You will finally be able to measure the success of your OJT programs. SkillsDB is a cloud-based talent management and training software platform used by hundreds of organizations worldwide. SkillsDB offers seamless integration with training tracking software, so that all trainings are tracked and reported at the same time. Company Benefits Your company’s goal is to maximize the productivity of employees while keeping the employees happy. Businesses are always looking for ways to help their employees adapt to technological change and maintain their competitive edge. This is why businesses are increasingly providing employees with OJT in order to stay up-to-date with changes in technology and contribute more towards the company’s goals. With OJT, employees can: Become better at their skillsets by learning from others Create better opportunities to grow and find interesting career paths Spend less time and money looking for new jobs Learning new skills that are not formally apparent in the workplace OJT has multiple benefits for both the business and its employees. It helps keep employees happy by offering them opportunities for advancement, while simultaneously increasing the productivity of these individuals who can learn new skills on their own time instead of during typical work hours. OJT offers a win win situation for both employees and employers. FAQ What is on-the-job training? On-the-job training (OJT) is learning that takes place at the work site during regular operations. It comes in formal and informal varieties, with formal OJT structured during work hours without taking away from the employee's core responsibilities. What are the best methods for on-the-job training? The three most effective formal methods are mentoring, online courses, and project-based experience. Each offers different advantages — mentoring provides personal guidance, courses deliver structured knowledge, and projects build practical skills through real work. How does mentoring work as on-the-job training? Experienced professionals provide one-on-one coaching to guide less experienced employees through real working conditions. Mentors offer advice, professional connections, and domain expertise that help mentees grow faster than self-directed learning alone. Why are online courses effective for OJT? Online courses give employees instant access to lectures, video tutorials, demonstrations, and quizzes. They allow employees to upskill at their own pace while staying current with industry trends — all from a central learning platform. What is project-based learning in the workplace? Project-based learning assigns employees to specific tasks within a defined timeframe. They learn not just the tasks themselves but the underlying skills required to complete them, gaining practical experience that classroom training cannot replicate. Why are spreadsheets bad for tracking training? Spreadsheets inevitably multiply across departments, each representing the same data without consolidation. They lack the ability to provide company-wide reporting, measure ROI, or connect training outcomes to skill-level improvements. How do you measure on-the-job training ROI? The most effective approach combines skill gap analysis with training tracking. By measuring starting and ending skill levels alongside completed training, you can directly quantify how OJT programs improve workforce capability. What software tools best manage on-the-job training? There are three categories: project management tools for tracking task completion, training tracking software for course monitoring, and talent management platforms like SkillsDB that combine skill gap analysis with integrated training tracking for full ROI measurement. What are the employee benefits of on-the-job training? Employees develop stronger skillsets by learning from colleagues, gain access to career growth opportunities, reduce job-search costs, and acquire skills that may not be formally taught. OJT is a win-win for both employees and employers. How does talent management software improve OJT tracking? Talent management software measures starting and ending skill levels, providing clear before-and-after data on training effectiveness. SkillsDB combines this with integrated training tracking, so organizations can finally quantify the success rate of OJT programs. --- ## Performance Review Competencies—What They Are and Why They Matter URL: https://skillsdb.com/blog/performance-review-competencies-how-to-integrate-competency-models The values and behaviors necessary for employees to succeed in their roles are best defined through performance review competencies. Competency-based performance reviews are a powerful method for evaluating how effectively someone performs over a given period—and more importantly, how they can grow. To make this process even more valuable, many organizations are now integrating competency training and using competency-based learning platforms to support ongoing employee development. Performance Reviews: Time to Do Them Right Performance review competencies give you the tools to write timely, accurate, and meaningful reviews. But what exactly goes into them? What Are Performance Review Competencies? Performance competencies refer to the skills, behaviors, and values that enable an employee to perform a job successfully. A competency model provides a practical framework that outlines what’s expected for a given role—defining what “good” looks like. By incorporating competencies into performance reviews, organizations can make evaluations more objective, consistent, and fair. A well-structured competency assessment tool like SkillsDB helps measure employee capabilities across key dimensions, making the review process less subjective and more actionable. Defining Competencies for Your Organization Typically, organizations define four types of performance review competencies: Core Competencies – Essential behaviors and values expected from all employees. Leadership Competencies – Skills necessary for individuals in leadership or managerial roles. Technical Competencies – Job-specific knowledge and technical skills. General Competencies – Soft skills like communication, collaboration, or adaptability. These competencies guide employees in understanding how to fulfill their roles effectively. Using Competencies in Performance Reviews Once you’ve aligned each job role with relevant competencies, they become powerful benchmarks for performance reviews. Instead of vague or subjective assessments, you’re evaluating employees based on clearly defined expectations. This approach fosters clarity, accountability, and growth—for both the employee and the organization. Why Competency-Based Reviews Work Competency-based evaluations offer several key benefits: Better hiring decisions : Core competencies help you identify candidates who align with your company’s values. Clear expectations : Employees understand what is expected and how to succeed in their roles. Objective feedback : Reviews are based on observable behaviors and outcomes—not opinions. Stronger development plans : Gaps in competencies highlight specific areas for improvement and growth. Increased engagement and productivity : When employees know how to win, they’re more likely to stay engaged and perform at a high level. Final Thoughts A competency-driven review process shows your commitment to employee success. It provides a clear path for development, aligns performance with company goals, and ensures fairness across the board. FAQ What are performance review competencies? Performance review competencies are the skills, behaviors, and values that define what success looks like in a given role. They provide a structured framework for evaluating employees based on clearly defined expectations rather than subjective opinions. What are the four types of competencies? Organizations typically define four types: core competencies (expected of all employees), leadership competencies (for managerial roles), technical competencies (job-specific knowledge), and general competencies (soft skills like communication and adaptability). How do competency models improve performance reviews? Competency models replace vague, subjective assessments with clearly defined benchmarks. This makes evaluations more objective, consistent, and fair — giving employees a concrete understanding of what is expected and how to succeed. Why are competency-based reviews more effective than traditional reviews? They provide objective feedback based on observable behaviors and outcomes, not opinions. This clarity drives better hiring decisions, stronger development plans, and increased employee engagement because people know exactly how to win. How do competencies help with hiring decisions? Core competencies help identify candidates who align with your company's values and culture. By defining what good looks like before the interview, you evaluate candidates against objective criteria rather than gut feeling. What is a competency assessment tool? A competency assessment tool like SkillsDB measures employee capabilities across key dimensions — skills, behaviors, and knowledge. It makes the review process less subjective and more actionable by providing structured, data-driven evaluations. How do competency gaps inform development plans? When reviews identify specific competency gaps, they highlight exactly where an employee needs to grow. This turns vague feedback into targeted development plans with clear objectives and measurable progress markers. How do competency-based reviews increase employee engagement? When employees understand what is expected and have a clear path to success, they are more engaged and productive. Competency frameworks remove ambiguity, so people can focus their energy on meaningful growth rather than guessing. How do you align competencies with job roles? Map each role to relevant core, leadership, technical, and general competencies that define success. These become the benchmarks against which employees are evaluated, creating consistency across teams and departments. What role does competency training play in reviews? Competency training and competency-based learning platforms support ongoing development between review cycles. Rather than reviewing once a year and hoping for improvement, continuous training closes gaps in real time. --- ## Technical Competencies vs. General. What is the difference? URL: https://skillsdb.com/blog/technical-competencies-vs-general-competencies-whats-the-difference Comparing technical competencies to general competencies can be tricky. Find out which matter most to your competency modeling effort. In this article, we will explore the different types of skills necessary for building a job role. And how they can vary from general to specific types of knowledge. If you’re exploring competency-based talent management for your organization, you’ll notice that there are 2 types of competencies: General Competencies and Technical Competencies. These two types have their individual characteristics which should be taken into account when they are being used in your organization. To better understand how to use competency modeling as a tool check this article out: Competency Based Assessments: The Foundation for Success in the Business World . A well-structured competency assessment plays a vital role in identifying and developing these competencies through a competency based training program. In This Article: General competencies consist of a broad range of soft skills—creativity, problem solving, teamwork—whereas technical competencies are specific to a given industry and require constant training and reinforcement. It’s important to have a skillset that reflects the needs of the present and future. What is the right combination of skills for your competency model? What is a General Competency? To begin with, general and technical competencies are not an “either/or” proposition. Every organization—and every employee—requires some combination of both technical and general competencies in order to thrive. General competencies are a blend of knowledge, abilities, motivations, and traits needed to perform a variety of tasks. Soft skills are often referred to as people skills which are necessary in contexts & occupations. If you need to learn more about what general competencies are, I recommend checking out. Examples of general competencies include interactive communication, social responsibility and achievement orientation. Candidates with these skills do a better job as they deliver value to the organization, whether they’re being considered for a salesperson, a CTO or a safety engineer. Though, general competencies only tell half the story. What are Technical Competencies? Technical competencies refer to a range of skills relating to any position requiring specific learning and/or training necessary for employees to perform their jobs. Thus, closely aligned with an employee’s ability to know and use knowledge, such as what you need to use specific information in order to do a particular task. A competency based training program can help employees strengthen both technical and general competencies to meet job-specific expectations more effectively. Why is this important to know the difference between general and technical competencies? For example, when you’re looking for a safety engineer, consider someone who can speak on behalf of your company to the public, as well as having the personal qualifications to plan effectively for emergencies and crises. In Summary Every job profile needs a combination of general and technical competencies in order to capture the complete picture of the ideal candidate. To determine the right combination, you need to understand how these two types of competencies fit into the organization’s competency architecture. FAQ What is a general competency? A general competency is a blend of knowledge, abilities, motivations, and traits needed to perform a variety of tasks. These soft skills — like communication, teamwork, and problem-solving — apply across all roles, industries, and organizational levels. What are technical competencies? Technical competencies are job-specific skills that require specialized learning or training. They are closely tied to an employee's ability to apply particular knowledge to complete specific tasks, such as forensic accounting or mechanical engineering. How do technical and general competencies differ? General competencies are transferable soft skills that apply across roles and industries. Technical competencies are role-specific hard skills that require constant training and reinforcement. Every effective job profile needs a combination of both. Why do job profiles need both competency types? General competencies alone only tell half the story — they do not capture the technical expertise a role demands. Technical competencies without soft skills produce employees who cannot collaborate effectively. The right combination captures the complete picture. What are examples of general competencies? Examples include interactive communication, social responsibility, achievement orientation, creativity, and teamwork. These people skills deliver value regardless of whether someone is a salesperson, CTO, or safety engineer. What are examples of technical competencies? Technical competencies vary by industry and role. Examples include software engineering, forensic accounting, emergency planning, mechanical engineering, and data analysis. They require formal training and regular updating to stay current. How does competency modeling use both types? Competency modeling maps the right combination of general and technical competencies to each job profile. This creates a complete picture of the ideal candidate and provides clear expectations for performance evaluation and development. How do you determine the right competency mix? Understand how both competency types fit into your organization's architecture. Some roles lean heavily on technical skills, others on soft skills — but every role benefits from a deliberate balance tailored to its specific demands. How does a competency assessment help organizations? A competency assessment identifies strengths and gaps across both technical and general competencies. Platforms like SkillsDB help organizations measure these systematically, turning subjective impressions into actionable development data. What is competency-based training? Competency-based training programs develop both technical and general competencies to meet job-specific expectations. Rather than generic learning, they target the exact skills an employee needs to perform effectively in their role. --- ## Competency Framework: How to Build One (Models, Methods, and Examples) URL: https://skillsdb.com/blog/competency-models-4-creation-methods-how-well-they-perform Every organization already has a competency framework. Most of them just haven't written it down. It lives in the heads of the managers who decide who gets the hard project, who gets promoted, and who gets quietly routed around. The framework exists. It's just invisible, inconsistent, and impossible to develop against. Quick reference: Competency Framework — the short version of this post, with the one table that matters. Writing it down is the easy part. The hard part is writing down the one that's actually true for your organization, in your language, at a level of detail people will use — and then connecting it to something that measures whether anyone meets it. This article covers what a competency framework is, the four ways organizations build competency models, a six-step method for building a framework that gets used, a worked example, and the mistakes that turn frameworks into shelfware. What Is a Competency Framework? A competency framework is a structured definition of the competencies an organization needs, organized by role, job family, or level, with each competency described at defined proficiency levels. A competency is a cluster of related skills, knowledge, and behaviors that together produce effective performance in a role — "incident response," for example, rather than the dozen individual skills it contains. The framework states which competencies each role requires and what "meets the bar" looks like at each level, in observable terms. It is the reference point for everything downstream: what to assess, where the gaps are, what to train, who is ready for the next role, and what a candidate needs to show. A framework that stays in a document is a job description with extra steps. A framework connected to assessment becomes the operating system for talent decisions, because the definition of "good" and the measurement of who meets it live in the same place. Framework vs. Model vs. Library The terms overlap, and vendors don't help. Term What it is Scope Competency model The set of competencies and levels for one role or job family One role or family Competency framework The organization's full structure of models, shared competencies, and the scale they use Whole organization Competency library The catalog of competency definitions available to build models from Reference material A model is the answer for one role. The framework is how all the models fit together. The library is the parts bin. Most of the confusion in this space comes from vendors selling a library and calling it a framework. The Four Ways to Build a Competency Model There are four established methods for defining what a role requires. Each has a cost, a speed, and a failure mode. Externally developed models Pre-built frameworks from industry bodies, consulting firms, professional associations, or government sources. The fastest way to start from zero. Use them when you have no framework at all and need a defensible starting point, or when the role is heavily standardized by an external body — nursing, project management, cybersecurity. The cost is fit. External models describe the role in someone else's language, at someone else's level of granularity, and they inevitably include competencies nobody in your organization recognizes and omit the ones that actually differentiate performance. Every organization we have worked with in 18 years that adopted an external model unchanged ended up with a checkbox exercise. The ones that used it as raw material and rewrote it in their own words got a framework people used. Expert panel workshops Bring the people who actually know the role — the top performers, their managers, the customers of their work — into a room and define the competencies together. Use this for roles where performance is understood but undocumented, and where buy-in from the function matters as much as the output. It's fast, it produces language people recognize, and the people who wrote it will defend it. The cost is bias. Panels converge on what's familiar. They overweight the competencies of the people in the room and underweight the quiet ones that predict success. Structured facilitation and a diverse panel mitigate it. They don't eliminate it. Competency surveys Ask a broad population — everyone in the role, their managers, adjacent teams — to rate the importance and frequency of a candidate set of competencies. Use surveys to validate or prioritize a model that already exists, or to reach populations too large or dispersed for panels. Done through a survey tool, it's the cheapest method per person and the only one that scales to thousands. The cost is that surveys can only rank what you put in front of them. A competency missing from the instrument is missing from the result. Survey quality is model quality. Job task analysis Break the role into its tasks, then derive the competencies required to perform each one. Rigorous, task-anchored, and the standard approach for highly technical or safety-critical roles. Use it where the consequence of a competency gap is an incident: operations, maintenance, clinical, regulated manufacturing. It produces the most defensible model and the one auditors like best. The cost is time and detail. Task analysis generates hundreds of line items, and without a discipline for rolling tasks up into competencies it produces a procedure manual, not a framework. It also tends to over-describe routine work and under-describe judgment. Which one, then Almost nobody should pick one. The pattern that works: start from an external model or a library to avoid a blank page, run panels with the function to rewrite it in their language and cut what doesn't apply, validate and prioritize with a survey if the population is large, and use task analysis only for the roles where being wrong is expensive. The method mix follows the role's risk profile. How to Build a Competency Framework in 6 Steps 1. Decide what the framework is for Assessment, development planning, hiring, succession, compliance — the purpose sets the level of detail. A framework built for compliance needs task-level anchors. One built for career development needs fewer competencies with clearer progression between levels. Frameworks that try to serve every purpose at once serve none of them. 2. Start with roles, not competencies Inventory the roles and group them into job families. The framework hangs off roles; competencies that don't attach to any role are decoration. If your job architecture is a mess, fix enough of it to know which roles exist before you define what they require. 3. Define the competencies in your own language Use whichever of the four methods fits each role's risk. Write each competency as a competency definition : a name, a one-sentence statement of what it enables, and the skills and behaviors it contains. Aim for eight to fifteen competencies per role. Beyond that, nobody assesses honestly. 4. Set the proficiency scale and anchor every level Pick one scale for the whole framework — four or five levels is standard — and write observable anchors for each competency at each level. "Level 3: independently diagnoses and resolves incidents on production systems without escalation" is an anchor. "Intermediate" is not. The scale is what makes the framework measurable; see proficiency levels for how to build one. 5. Set the required level per role For each role, mark the level required in each of its competencies. This is the bar. It is also the moment the framework becomes useful, because required-versus-actual is a gap, and a gap is something you can close. 6. Connect it to assessment, then revise A framework that is never assessed against is fiction. Run the first assessment cycle within a quarter of publishing the framework. The results will show you where the anchors are unclear, where the required levels are wrong, and which competencies nobody can evaluate. Revise. A good framework changes every year; a dead one is perfect and untouched. Competency Framework Example A compressed example for a data center operations job family, three roles, five shared competencies, on a four-level scale (1 Foundational, 2 Working, 3 Advanced, 4 Expert). The number in each cell is the level the role requires. Competency Facilities Technician Shift Lead Site Operations Manager Critical systems operation (UPS, generators, cooling) 3 3 2 Method-of-procedure execution (MOP/SOP discipline, revision control) 3 4 3 Incident response (detection, escalation, containment, root cause) 2 4 3 Compliance and evidence (audit trails, certification currency, documentation) 2 3 4 People leadership (coaching, scheduling, performance conversations) 1 3 4 Read across a row and you see how a competency changes meaning by level. Read down a column and you see the role's shape. Compare a person's assessed levels against their column and you have their development plan. Compare a Facilities Technician's assessed levels against the Shift Lead column and you have their readiness for promotion. That's the whole point of the grid. Anchors sit behind each cell. Incident response at level 2 might read "recognizes alarm conditions and escalates within defined thresholds." At level 4: "leads response across sites, directs containment, owns root-cause analysis and corrective action." Same competency, different job. Where Frameworks Go to Die Imported and never translated. A framework adopted wholesale from a generic taxonomy looks impressive in a demo and withers on the vine, because no two organizations define competency the same way. If the people being assessed don't recognize the language, they don't engage with the assessment, and the framework becomes shelfware inside a year. Levels without anchors. "Basic, Intermediate, Advanced" with no observable behavior behind each word produces assessments that measure the assessor's mood. Every level of every competency needs a sentence that two managers would read the same way. Too many competencies. Forty competencies per role is a job description, not a framework. Nobody can hold forty in their head, and assessment fatigue sets in by number twelve. Never connected to assessment. The framework is published, admired, and filed. Without an assessment cycle it cannot tell you where the gaps are, and a framework that can't find gaps can't justify its own existence at budget time. Frozen. Roles change. Technology changes. A framework locked to protect the effort that built it is measuring last year's job. The common thread is that the framework was treated as a document. It's infrastructure. It has to be built in the organization's own language, carry a scale people can apply, and sit inside a system that assesses against it, finds the gaps, and drives development — which is what competency frameworks in a skills platform are for. The Framework Is the Definition of Good. Assessment Is Whether Anyone Meets It. A competency framework is where an organization writes down what it means by good work, role by role, level by level. Done well, it stops being an HR artifact and becomes the reference every talent decision points at: what to hire for, what to develop, who is ready, and what the audit needs to see. Done badly, it's a PDF. The difference is not the method you chose to build it. It's whether you built it in your own words and connected it to measurement. FAQ What is a competency framework? A competency framework is an organization's structured definition of the competencies each role requires, described at defined proficiency levels in observable terms. It organizes competency models for individual roles under one shared scale and set of definitions, and it serves as the reference point for assessment, gap analysis, development planning, hiring, and succession. What is the difference between a competency framework and a competency model? A competency model defines the competencies and required levels for a single role or job family. A competency framework is the organization-wide structure that all the models fit into, including the shared proficiency scale and common competency definitions. A competency library is the catalog of definitions used to build models; it is a source, not a framework. What are the four types of competency models? The four established methods for building a competency model are externally developed models from industry or professional bodies, expert panel workshops with top performers and managers, competency surveys across a role population, and job task analysis that derives competencies from the tasks a role performs. Most organizations combine them according to each role's risk profile. How many competencies should a role have? Eight to fifteen is the practical range. Fewer than eight usually means competencies are too broad to assess meaningfully; more than fifteen leads to assessment fatigue and lower-quality ratings. Roles in safety-critical operations often run toward the higher end because task analysis produces more granular requirements. What proficiency scale should a competency framework use? One scale for the whole framework, typically four or five levels, with observable behavioral anchors written for every competency at every level. The scale itself matters less than the anchors; a four-level scale with clear anchors produces more consistent assessments than a seven-level scale without them. How often should a competency framework be updated? Review it after every assessment cycle and revise at least annually. Assessment results reveal unclear anchors, mis-set required levels, and competencies that cannot be evaluated. Roles and technology change, so a framework that has not been revised in two years is describing a job that no longer exists in that form. --- ## Employee Development Plan: Templates, Examples, and How to Build a Development Path URL: https://skillsdb.com/blog/competency-development-plan-all-you-need-to-know Most employee development plans are written once a year, in the same week as the performance review, by a manager who has forty minutes and a template with three empty boxes. They list a course, a stretch goal, and a conference. They're filed. Nobody opens them again until the next review, when the same three boxes get filled in with slightly different words. Quick reference: Employee Development Plan — the short version of this post, with the one table that matters. That isn't a development plan. It's a compliance artifact for the HR calendar. A development plan that works starts from a measured gap between what someone can do and what their role — or their next role — requires, and it ends with evidence that the gap closed. Everything else is scaffolding. What Is an Employee Development Plan? An employee development plan is a structured, time-bound agreement between an employee and their manager that identifies specific skill or competency gaps, sets development goals to close them, assigns the learning and experience that will get there, and defines how progress will be verified. A competency development plan is the skills-grounded version: each goal is tied to a named competency at a target proficiency level, so "improve communication" becomes "reach level 3 in stakeholder communication, as defined in the framework, by Q2." That precision is what separates a plan you can act on from a plan you can only file. The plan is individual, but it is only as good as the framework behind it. Without defined competencies and a proficiency scale, there is nothing to measure the gap against and nothing to prove the gap closed. With them, the plan becomes the operational link between assessment (where the person is), the role (where they need to be), and learning (how they get there). Development Plan vs. Career Path vs. Learning Plan Three documents that get confused with each other, and each does a different job. Development plan Career path Learning plan Scope One person, one period (typically 6–12 months) One person, multiple roles over years One person, one gap or one course sequence Starts from Assessed gaps against the current or next role Target roles and the competencies each requires A specific competency gap Contains Goals, learning, experience, evidence, review dates Sequence of roles, gaps at each step, readiness Courses, practice, mentoring, assessment Owned by Employee and manager Employee, with talent/HR L&D, assigned to the employee Answers What are we working on this year? Where is this going? How do we close this gap? A learning plan is a component of a development plan. A development plan is a step on a career path. Get the nesting right and the documents stop competing with each other. What Goes in a Development Plan Five elements, in order. Skipping any one of them is how plans turn into wish lists. Gaps. The assessed difference between current proficiency and the level the role requires, competency by competency. This comes from the assessment, not from the review conversation. If there is no assessment, the plan is guessing. Goals. Two to four competencies to move, each with a target level and a date. Two to four, not ten. A plan with ten goals has none. Learning and experience. For each goal, the intervention: a course, a stretch assignment, a rotation, a mentor, deliberate practice with feedback. The right mix depends on the competency. Procedural skills respond to practice. Judgment competencies respond to exposure and coaching. Almost nothing responds to a course alone. Evidence. What will show the level was reached. A reassessment, a manager observation against the anchor, a completed project reviewed against criteria, a certification. Decide this up front, or "done" becomes a matter of opinion. Review cadence. Monthly check-ins on progress, a formal reassessment at the end of the period. The annual review is far too slow a loop for development; by the time it arrives the plan is stale. Employee Development Plan Template The template is short on purpose. It fits on one page and lives in a system, not a document. Field What goes in it Employee / role / manager Current role and its competency requirements Target role (optional) The next role, if this plan is about readiness rather than current performance Assessment date and results Current level per competency, from the most recent assessment Priority gaps 2–4 competencies with current level → target level Development actions Per gap: learning, experience, support, owner, due date Evidence of completion Per gap: how the new level will be verified Check-in dates Monthly; who initiates Reassessment date End of period; feeds the next plan Worked row: Incident response, level 2 → 3 by end of Q2. Actions: shadow shift lead on the next four incidents; complete root-cause analysis training; lead one post-incident review with the shift lead observing. Evidence: shift lead assesses against the level 3 anchor after the third led review. Two Examples From engineer to senior engineer Priya is a software engineer assessed at level 3 in system design, where the senior role requires level 4, and at level 2 in technical leadership, where it requires 3. Everything else already meets the bar. Her plan has two goals. For system design: own the architecture for one new service end to end, present the design review, and have it assessed by two senior engineers against the level 4 anchor. For technical leadership: run the team's design review rotation for a quarter and mentor a new hire through onboarding, with her manager observing against the anchor. Six months, monthly check-ins, one reassessment. If both levels move, she's ready for promotion and the promotion conversation is about evidence rather than advocacy. From technician to operations lead, across functions Marcus is a facilities technician in a data center who wants to move into a site operations lead role — a different job family with a different competency profile. His assessment shows him at level 3 in critical systems operation (the lead role needs 2, so he's over the bar), level 2 in incident response (needs 4), level 1 in people leadership (needs 3), and level 2 in compliance and evidence (needs 3). This is a two-plan path, not one plan. Plan one, twelve months: incident response 2 → 3 through shadowing and leading post-incident reviews; people leadership 1 → 2 through covering shift scheduling and running toolbox talks; compliance 2 → 3 through owning the site's certification currency tracking. Plan two, the following year, takes incident response to 4 and leadership to 3 with a formal acting-lead rotation. The path is visible from the start, the gaps are named, and Marcus knows exactly what "ready" means. Building a Development Path, Not Just a Plan A development plan closes one set of gaps. A development path chains plans across roles so the employee can see where the sequence leads. The path starts with a target role and its competency profile, compares it against the person's current assessment, and lays out the sequence of plans that closes the distance — usually two to four, each six to twelve months. Every plan on the path is grounded in the same framework and the same proficiency scale, so progress is cumulative and comparable. When Marcus reaches level 3 in incident response, that's not a note in his file; it's a data point that updates his readiness for every role that requires it. This is where internal mobility actually comes from. People don't leave companies because there's no ladder. They leave because they can't see the next step or what it would take to get there. A development path built on assessed competencies replaces "someday" with a named role, a named set of gaps, and a plan for each one. Career pathways that show this to the employee, not just to HR, change the retention math. Running Development Plans at Scale It is clear how to help one person learn and grow. The hard part is scaling this from 3 to 300 people. At three people, a manager can hold the gaps, the goals, and the check-ins in their head. At thirty, the plans live in a shared drive and half of them are out of date by the second quarter. At three hundred, nobody can answer the questions that matter: which competencies are the most common gaps across the organization, which development actions actually move levels, which plans are stalled, and who is ready for which role right now. Scaling requires four things the annual-review template can't provide. Every plan starts from the same assessment data, so gaps are measured, not asserted. Every goal points at a competency and level in the shared framework, so progress is comparable across people and teams. Learning is assigned from the gap, so the intervention matches the deficit rather than the catalog. And reassessment closes the loop, so the organization learns which development actions work and stops paying for the ones that don't. That's the difference between talent development as an annual ritual and talent development as an operating capability. The template is the same either way. What changes is whether it sits inside a system that measures the gap, assigns the learning, and verifies the result. Development Is a Measured Gap With a Deadline Strip away the forms and a development plan is three facts and a promise: here is where you are, here is where the role needs you to be, here is what we're doing about it, and here is how we'll know it worked. Any plan that can't state all four isn't ready to be signed. Any organization that can state them for three hundred people at once has stopped guessing about its own capability. FAQ What is an employee development plan? An employee development plan is a time-bound agreement between an employee and their manager that identifies specific competency gaps against the current or next role, sets two to four development goals with target proficiency levels and dates, assigns the learning and experience to reach them, and defines how the new level will be verified. It typically covers six to twelve months with monthly check-ins. What is the difference between a development plan and a career path? A development plan covers one person for one period and closes a defined set of gaps. A career path covers one person across several roles over years, showing the sequence of roles, the competency gaps at each step, and current readiness. A development path is the chain of plans that moves someone along a career path, each grounded in the same competency framework. What is a competency development plan? A competency development plan is a development plan in which every goal is tied to a named competency at a target proficiency level from the organization's competency framework. Instead of "improve leadership," the goal reads "reach level 3 in people leadership by Q3, verified by manager assessment against the level 3 anchor." The precision makes the gap measurable and the outcome provable. How many goals should a development plan have? Two to four. Each goal should move one competency by one level within the plan period, which is a meaningful amount of work when the interventions include real experience and not just courses. Plans with more goals spread effort too thin, and in practice none of the goals get the sustained attention needed to move a proficiency level. How often should development plans be reviewed? Monthly check-ins on progress against each action, and a formal reassessment of the targeted competencies at the end of the plan period, usually six or twelve months. The annual performance review is too slow a cycle to drive development; by the time it comes around the plan is out of date and the evidence of progress has gone stale. How do you run development plans for hundreds of employees? Start every plan from the same competency assessment so gaps are measured rather than asserted, tie every goal to a competency and level in a shared framework so progress is comparable, assign learning from the gap rather than from the catalog, and reassess at the end of each period. That structure is what lets an organization see which gaps are most common, which interventions work, and who is ready for which role. --- ## Competency Based Assessments: A Critical Tool for Success URL: https://skillsdb.com/blog/competency-based-assessments Employees aren’t born job-ready—especially not straight out of college. Competencies must be developed over time, and to do that effectively, organizations need a clear view of their workforce’s current capabilities. This is where competency-based assessments come in. Whether you’re hiring, developing, or retaining talent, competency assessments offer a structured, reliable approach to identify strengths, gaps, and growth opportunities. Why Competency-Based Assessments Matter In today’s fast-changing business environment, success relies on capable, adaptable people. To develop employees strategically, companies must first understand where individuals stand today—and where they need to go. Competency-based assessments provide the data-driven foundation for making this possible. When paired with a robust employee skills platform, these assessments: Create a clear picture of your workforce’s current competencies Guide targeted training and development initiatives Improve performance evaluations and succession planning Boost employee engagement and retention through transparency and ownership When employees understand what’s expected—and see a clear path to improvement—they become more motivated, confident, and committed to their careers within your organization. Types of Competency-Based Assessments Competency assessments can be integrated throughout the employee lifecycle. Here are five essential types to consider: Written Tests (During Recruitment) These are typically the first filter in the hiring process. Written or online tests assess foundational skills and domain-specific knowledge, helping identify candidates who meet baseline competency requirements. ✅ Best for: High-volume roles, early screening, certified skills validation 🔍 Includes: Technical skills, problem-solving, communication, logic Interviews (Recruitment & Evaluation) Interviews allow for a deeper exploration of behavioral and situational competencies. Candidates are assessed on how they’ve handled past challenges and how they approach hypothetical ones. ✅ Best for: Evaluating practical understanding, critical thinking, leadership, collaboration 🧠 Pro tip: Use structured, competency-based interview questions tied to job-specific models Skill-Gap Assessments (Post-Onboarding) After initial training, new hires undergo skill-gap assessments to identify areas needing further development. These assessments align recruits to their future team’s expectations and set the stage for continuous learning. ✅ Best for: Onboarding, L&D alignment, performance benchmarking 📈 Tool tip: A competency-based learning platform helps track and address gaps efficiently Self-Assessments (6–12 Months in) Once an employee is settled into their role, self-assessments allow them to reflect on their progress. This empowers them to take ownership of their growth and prepare for meaningful performance discussions. ✅ Best for: Career planning, goal setting, boosting self-awareness 📊 Enhancement: Use interactive digital tools for real-time insights and progress tracking Manager Feedback & Performance Reviews Manager evaluations complete the loop by providing an external perspective on the employee’s competencies. When compared with self-assessments and role expectations, this creates a well-rounded view of performance and development needs. ✅ Best for: Performance reviews, promotion readiness, succession planning 🔁 Repeat: This full-cycle assessment process (Points 3–5) should repeat every 6–12 months to keep pace with business change How SkillsDB Supports Competency-Based Assessments SkillsDB simplifies the entire process—from skill- gap analysis and self-assessments to manager reviews and learning plan creation. We help organizations: Streamline their assessment workflows Align competency frameworks to job roles Generate actionable insights for training and development Integrate with existing LMS systems for seamless learning delivery With SkillsDB, implementing a competency-based assessment strategy becomes easy, fast, and effective—unlocking employee potential and accelerating organizational growth. Further reading: Skills & Competencies, Similar but Different How to best Implement a Competency-Based Training Program Good people will leave you! How can a good succession plan help? FAQ What are competency-based assessments? Competency-based assessments are structured evaluations that measure an employee's skills, behaviors, and knowledge against defined role requirements. They provide a data-driven foundation for identifying strengths, gaps, and growth opportunities across the workforce. Why do competency-based assessments matter for organizations? They give organizations a clear, measurable picture of workforce capabilities, which drives better decisions around training, performance reviews, and succession planning. When employees understand what is expected and see a path to improvement, engagement and retention increase. What types of competency assessments exist? The five essential types are written tests during recruitment, competency-based interviews, skill-gap assessments post-onboarding, employee self-assessments, and manager feedback and performance reviews. Each serves a different stage of the employee lifecycle. When should skill-gap assessments be conducted? Skill-gap assessments are typically conducted after initial onboarding and training. They align new hires to their team's expectations and establish a baseline for continuous learning and development. How do self-assessments benefit employee development? Self-assessments empower employees to reflect on their own progress, take ownership of their growth, and prepare for meaningful performance discussions. They are most effective when conducted 6 to 12 months into a role and repeated regularly. How often should competency assessments be repeated? The full-cycle assessment process, including skill-gap analysis, self-assessments, and manager reviews, should repeat every 6 to 12 months. This cadence keeps pace with business changes and ensures development plans stay relevant. What role do managers play in competency assessments? Managers provide an external perspective on employee competencies through formal evaluations and performance reviews. When combined with self-assessments and role expectations, this creates a well-rounded view of performance and highlights specific development needs. How are written tests used in competency-based hiring? Written or online tests serve as the first filter in recruitment, assessing foundational skills and domain-specific knowledge. They are most effective for high-volume roles and early screening where baseline competency requirements need to be validated quickly. How does SkillsDB support competency-based assessments? SkillsDB streamlines the entire assessment process from skill-gap analysis and self-assessments to manager reviews and learning plan creation. It aligns competency frameworks to job roles, generates actionable insights, and integrates with existing LMS systems for seamless learning delivery. Can competency assessments improve employee retention? Yes. When employees have transparency into expectations and a clear development path, they become more motivated and committed to their careers within the organization. Competency assessments create this transparency by making growth opportunities visible and actionable. What is a competency-based interview? A competency-based interview uses structured questions tied to job-specific competency models to evaluate how candidates have handled past challenges and approach hypothetical ones. It is effective for assessing practical understanding, critical thinking, and leadership capabilities. --- ## The 4 Pillars of Writing Competency Definitions URL: https://skillsdb.com/blog/the-4-pillars-of-writing-competency-definitions Clear competency definitions help employees and managers with specific guidelines on what every level means and how to evaluate their staff. What is a competency definition? You have discussed and finalized the different skill levels for your competency evaluation. But how to accurately classify your workforce on the scale you have zeroed in on? Employees have a hard time deciding what skill level they currently are at if they do not have a clear understanding of what each level represents. Managers face the same dilemma while evaluating. During designing these different levels, organizations need to follow the 4 pillars of writing competency definitions . Employees and Managers need to understand what different competency levels are. This enables them to identify where they are and discover the improvements needed to rise up. Similarly, skills-based organizations also need to understand this basic fact. They have to describe various levels of a job and what every skill/competency level signifies. How to understand any given Job? It is crucial to know what all constitutes a given Job role . This, in turn, would help us in designing the competency definition closest to what we require. The Job is the collection of Roles, Tasks, and Activities. For example, let’s take the Job of a paint-booth supervisor at an automobile manufacturing plant. The Role is the outlined function of a job. The role of the paint-booth supervisor is to make sure that all vehicles should have a uniform quality of paint finish with pre-defined color accuracy. The Task is a section of the job or role with clearly defined responsibilities. One of the tasks of a paint-booth supervisor is to make sure that the paint robots are applying a uniform coat of paint. Activity is basically an action undertaken to fulfill a task at hand. The paint-booth supervisor will have to make sure that the machines are serviced regularly and their sensors are monitored, checked, and cleaned. Finally, we need to factor in the 4 pillars of writing competency definitions Identifying similarities and differences between competencies: Sometimes we try and club different competencies under one heading. This can reduce the number of competencies in a job role. However, sometimes, it can cause incorrect evaluations. For example, good people skills need not lead to good leadership skills so clubbing them together is a bad idea. Describing the competencies in clear and simple terms: The easier the level descriptions are to understand, the better the evaluation will be. Clear definitions are vital for effective competency assessment. Descriptions should have objective terms: If we can define levels based on clear pre-defined objective terms, we will get a more accurate evaluation. Having a useful outcome/data to work on: Having defined metrics helps in the clear demarcation of levels. This in turn leads to a more accurate evaluation. Which in turn leads to the effective development of future learnings—often delivered through a structured competency based training program. In Conclusion If we can take into account these 4 pillars, we will have an accurate picture of where our employees stand. What their individual competencies are, where they should be and what needs to be done to get there. We at SkillsDB cannot emphasize enough the importance of having clear, understandable, and differentiable competency levels. In fact, it is one of the first things we ask our clients to decide upon before starting their competency evaluations. Further Reading: Skills & Competencies, Similar but Different How to best Implement a Competency-Based Training Program Competency Based Assessments: The Foundation for Success in the Business World FAQ What is a competency definition? A competency definition is a clear description of what each proficiency level means for a given skill or competency. It gives employees and managers specific guidelines for understanding expectations and accurately evaluating performance at each level. What are the four pillars of competency definitions? The four pillars are: identifying similarities and differences between competencies, describing competencies in clear and simple terms, using objective terminology in descriptions, and ensuring definitions produce useful, measurable outcomes. Together, they create accurate and actionable evaluation criteria. Why should competency definitions use objective terms? Objective terms eliminate ambiguity and personal interpretation from evaluations. When levels are defined by clear, pre-defined criteria rather than subjective language, organizations get more accurate and consistent assessments across teams and departments. How do unclear competency definitions affect evaluations? When definitions are vague or confusing, employees struggle to self-assess accurately and managers evaluate inconsistently. This leads to unreliable performance data, misaligned development plans, and frustration on both sides of the evaluation process. Why not combine similar competencies into one definition? Clubbing related but distinct competencies together can cause incorrect evaluations. For example, strong people skills do not necessarily indicate strong leadership skills. Keeping competencies separate ensures each one is measured on its own merits. How do you break down a job role for definitions? A job role is broken into four layers: the overall job (collection of functions), roles (outlined functions), tasks (defined responsibilities within a role), and activities (specific actions to fulfill tasks). This hierarchy helps you write competency definitions that match real work. What makes a competency definition easy to use? The best definitions use simple, clear language that any employee can understand without HR jargon. When level descriptions are straightforward and unambiguous, both self-assessments and manager evaluations become faster and more accurate. How do measurable outcomes improve competency definitions? Defined metrics create clear demarcation between proficiency levels, removing guesswork from evaluations. This produces more accurate assessments, which in turn lead to better-targeted development plans and more effective training investments. When should organizations define competency levels? Competency levels should be defined before starting any evaluation or assessment process. At SkillsDB, this is one of the first steps recommended for clients, because every downstream decision depends on having clear, understandable, and differentiable level definitions. Can poor competency definitions derail a training program? Yes. If employees and managers cannot accurately determine current proficiency levels, the resulting gap analysis will be flawed. This means training resources get directed at the wrong skills, wasting time and budget while real gaps remain unaddressed. --- ## How to Implement a Competency-Based Training Program in 5 Phases URL: https://skillsdb.com/blog/how-to-best-implement-a-competency-based-training-program To stay on top of the competition, organizations need to keep evolving. They need to keep unlearning and relearning. Their employees in turn need to be in a constant cycle of improvement. Competency-based evaluation and training are the need of the hour. Simply buying a solution, however, will not get you far. Organizations need to figure out how to best implement a Competency-Based Training Program. Only then can we efficiently and effectively utilize the tools at our disposal. Planning phase Organizations need to figure out a few foundational issues first. We need to answer the question: How to best implement a competency-based training program? What core competencies will a job role have? How To Create A Competency Definition For Your Organization? What is the desired competency level for various job roles? How to effectively communicate the various competency levels and their expectations? How will we evaluate employees on these core competencies? What to expect out of the employees? HR needs to deliberate with various team leaders and managers to finalize these details. This will avoid changes post-implementation. As a result, it will lead to more uniform and efficient implementation across the organization. It is ideal to have a clear outline of expectations and goals. For a more detailed article on the planning phase, read this article . Evaluation/Assessment Phase Employees need to engage in self-assessment of skills/competencies outlined in their job roles. Further, Managers have to take up the role of supervisory assessment to confirm employee assessments. It can sometimes be a challenge to positively express the need for evaluation/assessment. Hence, organizations need to educate employees and managers about the need and importance of accurate evaluation. They need to outline the benefits and their effect on competency management and career growth. This stage is ideal for conducting competency assessment using structured tools that align with defined job roles. Gap Assessment and Mitigation Phase Post assessments, we need to identify and highlight skill gaps. With desired skill levels and core skills identified in the planning phase, Organizations need to design and implement learnings. These learnings are basically courses, trainings, certifications, etc. which will improve skill levels. Implementation Phase It is probable that employees will have multiple skill gaps when assessments are done for the first time. Maybe the organization wants a higher skill level from its employees. Maybe the employees and managers are too conservative in their assessments. In any case, organizations should assign learnings based on their needs. Different skills need different types of training. Employees can undertake some Competency-Based Training Programs via classroom sessions. However, individual employees will have to do most of the trainings alone. The plus side is that employees have the flexibility to complete them at their own pace and comfort. Further, some employees have better knowledge about a subject than others. While some have different ways to learn. Some employees need more time than others to finish the same learning. All this is completely fine and organizations need to be flexible in approaching employees. Training Phase Post assessments, the next challenge will be handling skill gaps. What to do now that the skill level is lower than desired? Organizations need to design and develop a training phase that will cater to bridging these gaps. Luckily, the solution can be as simple as using an existing LMS or subscribing to one available. If an organization already has an LMS in-house, that works too. SkillsDB gives you the flexibility to incorporate any of these LMS into our competency management system. While designing these systems, organizations do need to focus on a few things beyond the scope of courses/trainings on offer. First, the LMS has to be easy to use. If the employee has to spend a lot of time just to learn how to learn, it’s a simple waste of time. Organizations need to motivate their employees to take these courses/training. Employees have to be sensitive to skill development and its need in their career development. They also have to be convinced of the organization’s needs and their role in fulfilling them. Organizations also need to ensure employee work-life balance while implementing these trainings. Employees generally take time out of their personal time to work on self-development. Organizations need to create a balance here. It is not just the employee who is going to benefit from these programs. Post completion of learning, employees need to be evaluated once again to see if the learnings have been of any help. Managers have to make sure that the learnings assigned to employees are helping them and not just wasting everyone’s time. Using a competency based learning platform can help streamline this process while offering measurable outcomes Review and Repeat Organizations need to take feedback from their employees/managers, once they have used the system. Feedback on how the LMS has helped and how it can improve. This feedback loop helps by customizing the system for a more efficient competency management system. Further, this ensures that our competency-based training program is effective in achieving our goals. For a customized demo of our competency-based management software, schedule something from this link: book a demo . Further Reading: Skills & Competencies, Similar but Different Good people will leave you! How can a good succession plan help? FAQ What is a competency-based training program? A competency-based training program is a structured approach to employee development that ties learning directly to defined competencies required for specific job roles. It ensures training efforts close real skill gaps rather than delivering generic content. What are the phases of competency-based training implementation? Implementation follows five phases: planning (defining competencies and expectations), evaluation and assessment, gap assessment and mitigation, implementation of learning programs, and training delivery. A final review-and-repeat cycle ensures continuous improvement. What happens during the planning phase? During planning, organizations define core competencies for each job role, establish desired proficiency levels, and determine how to communicate expectations. HR collaborates with team leaders and managers to finalize these details before implementation begins. How do you assess employee competencies effectively? Employees complete self-assessments of their skills against defined role competencies, followed by supervisory assessments from managers. Organizations must clearly communicate the purpose and benefits of evaluation to ensure honest, accurate participation from both sides. What is a skill gap assessment in this context? After initial assessments, organizations compare actual proficiency levels against desired levels to identify gaps. These gaps then drive the design of targeted learning programs, including courses, certifications, and training that will close specific deficiencies. How should organizations handle multiple skill gaps at once? When first-time assessments reveal numerous gaps, organizations should prioritize based on business needs and assign learning accordingly. Different skills require different training approaches, and employees should have flexibility to complete them at their own pace. What role does an LMS play in competency-based training? An LMS delivers the training content that closes identified skill gaps. It should be easy to use so employees spend time learning rather than navigating the platform. SkillsDB integrates with any LMS to connect competency management directly to learning delivery. How do you maintain employee work-life balance during training? Organizations must recognize that employees often invest personal time in development. Since the organization benefits equally from improved competencies, leaders should create reasonable timelines and provide dedicated learning time within the workday. Why is post-training evaluation important? After completing training, employees need to be reassessed to determine whether the learning actually closed the targeted gaps. Without this step, managers cannot verify that training investments are producing results or identify where additional support is needed. How does the review-and-repeat cycle improve the program? Collecting feedback from employees and managers after each cycle reveals what is working and what needs adjustment. This continuous feedback loop customizes the system over time, making each iteration more efficient and better aligned with organizational goals. Why should HR involve managers in the planning phase? Involving managers early prevents changes after implementation and ensures competency definitions reflect actual job requirements. Managers bring frontline perspective on what competencies matter most, leading to more uniform and effective deployment across the organization. --- ## Skills vs. Competencies vs. Proficiency: The Difference, With Examples URL: https://skillsdb.com/blog/skills-competencies-similar-but-different A skill is a specific ability a person has learned. A competency is a job-relevant bundle of skills, knowledge, and behavior tied to a work outcome. Proficiency is how well the person performs either one, measured on a scale. Three words, three different objects, and most workforce frameworks blur them into one. Quick reference: Skills vs. Competencies vs. Proficiency — the short version of this post, with the one table that matters. The blurring is expensive. When "skills" and "competencies" mean the same thing in a framework, the taxonomy grows to 400 items nobody can assess. When "proficiency" gets folded into "competency," ratings become a yes/no checkbox and the organization loses the ability to see who is one level away from qualified. The three terms are doing different jobs. Keep them separate and the framework gets smaller, sharper, and usable. The Difference at a Glance Skill Competency Proficiency What it is A learnable ability A cluster of skills, knowledge, and behavior tied to a job outcome A measured level of performance Scope Narrow, specific Role-relevant, composite Applies to a skill or a competency Example Write a SQL join Build reporting pipelines finance signs off on Level 3 of 5 on that competency, assessed last quarter How it is written Noun or short verb phrase Action verb, object, standard, result Level descriptors with behavioral anchors How it is measured Has it or not; sometimes a simple scale Leveled rubric The scale itself Who owns it Skills library Job family or role framework Assessment process Decays? Yes, by practice Yes, as the role changes Yes, recency matters Skills are the base unit. Competencies organize skills into what a role needs. Proficiency measures where a person stands against either. The rest of this post takes each pair in turn, because each pair is a question people actually ask. Skills vs. Competencies Skills and competencies are similar in one way: both describe a capacity to perform, and both are acquired through practice and training. That is where the similarity ends. A skill is specific and often assessed simply. Can this person weld a TIG joint on stainless? Can they configure a VLAN? Can they run a pivot table? The skill tells you whether the person can do the discrete thing. It says little about whether they can do the job. A competency is what the job actually needs, written as a package. It combines several skills with the knowledge to know when to use them and the behavior to apply them under real conditions. "Weld a TIG joint" is a skill. "Produce code-compliant stainless welds on pressure-bearing assemblies, inspect them against the WPS, and document results for the quality record" is a competency. The competency is assessable at levels, points at an outcome an auditor or a customer cares about, and would appear in a role profile. The skill would appear in a skills library. The practical test: if you can imagine a course teaching it in an afternoon, it is probably a skill. If you can imagine a manager rating someone on it across a year of work, it is probably a competency. How to write competencies that pass that test is covered in What Are Competencies? Definition, Types, and Examples . Why the distinction matters in a framework Organizations that treat every skill as a competency end up with frameworks that are too large to assess. Organizations that treat every competency as a skill end up with binary checklists that cannot distinguish a new hire from a twenty-year expert. The healthy structure is a skills library of specific abilities, with role competencies assembled from them. A role typically requires 8 to 12 competencies, each drawing on a handful of skills. That is small enough to assess quarterly and rich enough to plan against. Competence vs. Competency This one is a spelling question that hides a real distinction, and almost nobody answers it well. Competence is a state. It is the condition of being able to do something to the required standard. "She has demonstrated competence in medication administration." It is uncountable in ordinary usage; you do not have three competences, you are competent or you are not, in a given domain. Competency is a thing. It is a defined, named, assessable unit inside a framework. "Medication administration is one of nine competencies in the nursing framework." Competencies are countable, written down, leveled, and assigned to roles. So the sentence "we assess competence against competencies" is correct and not redundant. The framework lists competencies. The assessment establishes whether the person has reached competence in each. British and American usage both accept this split, and it is the split that regulated industries lean on: an auditor asks whether you can demonstrate competence, and your evidence is a set of assessed competencies with dates and levels. Where people go wrong is using "competences" as a plural of "competence" to mean framework items. Some published frameworks do this, and it is not wrong, but inside one organization pick one convention. The cleanest is the one above: competency for the framework item, competence for the state a person achieves. Competency vs. Proficiency A competency is what the role requires. Proficiency is how well a specific person performs it today. The competency is fixed at the role level. "Diagnose process faults using P&ID drawings, instrument readings, and shift logs, and escalate per protocol" is the same competency for every operator on the unit. Proficiency varies by person and by time. One operator is at level 2, another at level 4, and the level 4 operator who has been on desk duty for a year may have slipped to a 3. That is why proficiency needs a scale with described levels, not a checkbox. A useful five-level scale for the fault-diagnosis competency reads: Foundational. Recognizes standard alarms and follows the checklist with guidance. Developing. Diagnoses routine faults independently; escalates anything unfamiliar. Proficient. Diagnoses complex and compound faults; coaches level 1 and 2 operators through them. Advanced. Anticipates faults from leading indicators; contributes to procedure revisions. Expert. Sets the standard; designs the training and assessment for the competency. The same scale shape works for skills. "Write SQL" can be assessed at level 1 through 5 just as a competency can. Proficiency is the measurement layer that sits on top of both. How to build these scales, choose the number of levels, and write anchors that managers apply consistently is in Proficiency Levels: Scales, Examples, and How to Define Them . One more property of proficiency that competencies do not have: it decays. A role competency is stable until the role changes. A person's proficiency drops when they stop practicing. A framework that records proficiency without a date is recording history and calling it current state. Eight Worked Examples The fastest way to internalize the three layers is to see them stacked. Each row maps one skill to the competency it serves and what proficiency looks like at the low and high end. Skill Competency it belongs to Proficiency level 2 looks like Proficiency level 4 looks like Write SQL queries Build reporting pipelines that finance relies on for close Writes correct queries against documented tables with review Designs pipelines, validates against source systems, owns data quality checks Read a P&ID drawing Diagnose process faults and escalate per protocol Locates instruments and traces routine flows Diagnoses compound faults from drawings plus live readings Operate a CNC lathe Produce first-pass-yield parts to the control plan Runs proven programs with setup verified by a lead Sets up new jobs, adjusts offsets, holds tolerance across a shift Take a patient history Complete admission assessments that drive the care plan Gathers required fields with prompts Elicits risk factors patients do not volunteer; flags them to the team Run a discovery call Qualify opportunities so pipeline forecasts hold Follows the script and records answers Adapts questioning to surface the buying process and decision criteria Configure a VLAN Deliver network changes without unplanned outages Implements approved changes in the maintenance window Designs segmentation, writes the rollback plan, reviews others' changes Build a project schedule Control scope and schedule to the approved baseline Maintains a schedule from a template Rebaselines with sponsor approval and quantified impact Coach a direct report Develop people so the team's bench strength grows Holds regular one-on-ones with agreed goals Moves people up a proficiency level per year with evidence Read down the first column and you have a skills library. Read down the second and you have a piece of a role framework. Read across and you have the assessment. That is the whole model. Why Organizations Need All Three The original version of this post argued that organizations should focus on competencies rather than skills. Years of implementations have made me more precise about that. You need all three layers, and you need them to stay distinct. Skills give you a shared vocabulary that survives reorganizations (the types and how skill sets group them are in What Are Skills? Types, Examples, and Skill Sets ). A skills library written in the organization's own language is the raw material every role draws on, and it is what lets you spot the person in operations who has the skill the analytics team is hiring for. Competencies give you role definitions that hiring, assessment, and succession can all reference. They keep the framework small enough to run. They are what you assess against when someone asks whether a team is qualified for the work. Proficiency gives you the truth about today. It tells you who is one level away from qualified, whose currency has lapsed, and where the training budget will move the needle. Without it, the framework describes the organization you wish you had. Vocabulary Is Infrastructure The three words look like a semantics problem. They are a data model. Skills are the entities, competencies are the role-level structures built from them, and proficiency is the measured attribute with a timestamp. Get the model right and every downstream question, from staffing to succession to audit, has an answer with evidence behind it. Get it wrong and the organization is running its workforce decisions on a glossary. FAQ What is the difference between skills and competencies? A skill is a single learnable ability, such as writing SQL or welding a TIG joint. A competency bundles several skills with the knowledge and behavior needed to produce a job outcome, such as delivering code-compliant welds with documented inspection results. Skills are the units; competencies are how a role organizes them. What is the difference between competence and competency? Competence is the state of being able to perform to the required standard. Competency is a defined, named, assessable item inside a framework. You assess a person's competence against the competencies listed for their role, so the two words work together rather than competing. What is the difference between a competency and proficiency? A competency is fixed at the role level and describes what the job requires. Proficiency is how well a specific person performs that competency right now, measured on a leveled scale. Two people share the same competency requirement but hold different proficiency levels, and a person's proficiency changes over time. Can a skill have a proficiency level too? Yes. Proficiency is a measurement layer that applies to skills and competencies alike. Rating "write SQL" on a five-level scale is just as valid as rating a full competency; the difference is only in how granular the thing being measured is. How many competencies should a role have? Most well-run frameworks assign 8 to 12 competencies per role or job family, each drawing on a handful of skills from the library. That is small enough to assess on a regular cycle and detailed enough to drive hiring, development, and succession decisions. Why do skills and competencies frameworks fail? They fail when the layers collapse into each other: every skill becomes a competency and the framework grows too large to assess, or every competency becomes a checkbox and the organization cannot tell a novice from an expert. Keeping skills, competencies, and proficiency as distinct layers keeps the framework usable. --- ## Competency Management and its Role in Aligning Competencies to Values URL: https://skillsdb.com/blog/competency-management-and-its-role-in-aligning-competencies-to-values How can you create a winning corporate culture? What values do you want to impart in your workforce? How is all this related to competency management? Values identification is important. You need to make sure that the values fit your organization’s culture. You also need to integrate these values with your workforce’s proficiency. Agreed, this is a complex process, and managers often find it hard to integrate them. But when you are successful, the employees will have a better road map to work for the organization’s vision. SkillsDB has a comprehensive competency management system with access to an extensive library of hard and soft skills. Our system is designed to make this complex process easy and accessible, just a few simple steps, and you are set. It seamlessly supports every phase of a competency based training program, ensuring values and proficiencies are aligned for long-term impact. Figuring out the way to identify competencies and define Culture and Values Your employees and their way of doing things play a vital role in shaping organizational culture. Employees are however made to believe that Organizational Values are defined at the top and implemented below. However, we often fail to understand that both employees and organizations play an almost equal role in shaping their values. Whatever decisions you take to create a corporate culture will affect your employees. But employees’ traits and values will also blend in and shape the organizational culture further. Therefore, it is imperative to formulate a competency management platform, which ensures that your culture, goals, values, and people are strongly integrated. A Typical Employee Life Cycle in Competency Management Here are the five stages of the employee lifecycle and competency management will be integral at each step. This system helps business leaders to keep an eye on integration between individual competencies and corporate values. Recruitment The process starts with recruiting, i.e. bringing fresh talent to the organization, getting the documentation, setting up the individual in the system, providing access to the organization, etc. Onboarding At this stage, the newly recruited talent is introduced to the organizational resources and information. This phase primarily works towards helping recruits navigate to their job role. Additionally, it helps them to understand the organizational culture and environment better. Performance Management The third step is fundamentally an evaluation step. It enables employees to self-evaluate themselves and then be evaluated by their managers. The feedback an employee gets from their manager and vice-versa creates a communication channel. Additionally, this also helps fresh recruits to understand the organizational values and culture in a better way. Similarly, the feedback from the talent helps the organization to identify the weak spots in their processes and improve them. Training and Development This is a stage where the organization utilizes its resources and “invests” them in their employees to develop a culture from scratch. This process is often termed as professional development. Many organizations don’t have a standard coaching method for a specific job role. In such cases, organizations need to create new methods. Especially those which integrate the core competencies of the employees and the organizational values. Using a structured competency based training program allows organizations to map training directly to gaps and business values. Career Pathing The needs and wants of any individual will change with time. Any organization first needs to acknowledge these needs and wants. Next, we need to design a career growth plan as per the employee’s desire and the organization’s goals. In the likelihood of employees leaving, good succession planning goes a long way in providing stability. Whenever an employee leaves, he/she leaves with the creativity and talent they were giving to the organization. But they leave behind the values they helped shape. Great organizations create a process for when employees depart the organization, they leave something valuable in their place. The company culture cycle is a continuous, never-ending process. The employees are first exposed to the values of the organization and the expectations from them. With time, these employees will give feedback and modify the company values based on their ideas. Just like the life cycle of a herbivore, which eats all the grass that comes out of the soil. Over the course of its life cycle, the herbivore will regularly return nutrients to the soil. Similarly, a strong organizational culture keeps strengthening the organization by adding value continuously. Competency management helps out every step of the way. Identifying different types of Competencies What are the different types of competencies and the differences between them? Job-related competencies are like necessary skills required for a specific job. For instance, having enough skills to work on a computer or having specific industry-related skills are considered job-related skills/competencies. Core competencies , on the other hand, are more like soft skills such as work ethic, teamwork, empathy, relatability, adaptability, etc. Let’s get a more detailed view of core competency with a practical example: customer service. Customer service requires a lot of empathy and relatability. Organizations often work hard to turn customer service into a value and then teach it as a core competency to their staff. You can give your employees training but sometimes it is still not enough. One great motivator is rewarding your staff, making them a stakeholder in providing excellent Customer Service. Conclusion Creating organizational values and then integrating them with these core competencies is not as easy as it might look. The management has to work side by side with that talent. There isn’t any shortcut for success, at least not in this case. The theory is simple; organizations need to integrate these two factors at all levels. Management who pay heed to this and evolve will achieve success. A robust competency based learning platform will help ensure these skills are consistently developed and nurtured across departments. To ensure this, identify what your values are and how you can align them with the competencies you want in your staff. It will transform your business in a much better way and that too for the long run. Once you have homed in on that, SkillsDB with its competency management solutions will do all the heavy lifting. Our solutions can create systems that will enable organizations to design, implement, reshape and re-implement. Leaders will be able to communicate what they are planning, what values do they want to promote, and where their organization is heading. On the other hand, the fresh recruits will have a better idea of what they are signing up for and what is expected from them. Further Reading: Best Practices in Skills Management Techniques The 4 pillars of writing competency definitions Skills & Competencies, Similar but Different Skills Matrix – Step by Step How to best Implement a Competency-Based Training Program Good people will leave you! How can a good succession plan help? New Hire Training FAQ How does competency management align with company values? Competency management integrates workforce proficiency with organizational values by ensuring that the skills employees develop support the company's culture and vision. When values and competencies are aligned, employees have a clear roadmap for contributing to organizational goals. What role do employees play in shaping organizational culture? Employees and organizations shape culture together. While values are often defined at the leadership level, employees' traits, behaviors, and feedback continuously blend in and reshape organizational culture over time. Effective competency management accounts for this two-way dynamic. What are the five stages of the employee lifecycle? The five stages are recruitment, onboarding, performance management, training and development, and career pathing. Competency management is integral at each stage, helping leaders maintain alignment between individual competencies and corporate values throughout an employee's tenure. How does competency management support onboarding? During onboarding, competency management helps new recruits understand their job role expectations alongside organizational culture and values. This dual focus ensures new hires navigate their responsibilities while absorbing the behavioral standards the organization expects. What is the difference between job-related and core competencies? Job-related competencies are technical skills required for a specific role, like operating equipment or using industry software. Core competencies are soft skills shared across the organization, such as teamwork, adaptability, empathy, and work ethic. How does performance management connect to competency development? Performance management creates a feedback loop where employees self-evaluate and receive manager assessments. This two-way communication helps fresh recruits understand organizational values while giving the organization visibility into process weaknesses that need improvement. Why is career pathing important for competency alignment? Career pathing acknowledges that employee needs change over time and designs growth plans that serve both individual aspirations and organizational goals. It also supports succession planning, ensuring that when employees leave, the values and competencies they helped build remain. How can customer service be developed as a core competency? Organizations can turn customer service into a core competency by combining training with incentive structures. Beyond formal training, rewarding employees and making them stakeholders in delivering excellent service creates genuine buy-in that drives consistent behavior. What makes aligning competencies to values difficult? The challenge lies in integrating two complex systems: organizational values that define culture and individual competencies that define capability. Management must work side by side with employees at all levels to weave these together, and there are no shortcuts to doing it well. How does SkillsDB simplify competency-values alignment? SkillsDB provides a comprehensive competency management system with an extensive library of hard and soft skills. It handles the heavy lifting of designing, implementing, and iterating on competency frameworks so leaders can focus on communicating values and driving organizational direction. --- ## Good people will leave you! How can a good succession plan help? URL: https://skillsdb.com/blog/good-people-will-leave-you-how-can-a-good-succession-plan-help Organizations ignore the need for a robust succession plan at their own peril. Having one will greatly impact the short and long term health of any organization. Further, it will help reduce many of the costs while increasing the overall competence of the workforce. A well-designed skills development program supported by an effective employee skills platform can make this process streamlined and efficient. We have all heard of the phrase “Any organization is only as good as its people”. While that is true, in our experience “Nobody is irreplaceable” also holds true. The bitter truth however is that “Good people will leave you.” Be it a better job, worsening health, or even death. People Leave In this information age, people change their jobs and careers multiple times. With access to so many avenues, it’s hard to keep anyone satisfied and motivated. Plan A in succession planning should focus on working with people you already have. It is essential for an organization to work with employees to identify their skill gaps and fill them. Effective skills assessment tools available in modern employee skills platforms help identify these gaps quickly and accurately. As the needs of any organization change and evolve, so does the requirement for skill development of its employees. Having a clear outline of what skills an employee has and what they need is paramount. We may be able to reduce employee churn but we can never eliminate it. Hence Plan B is to have more than one person ready, at least skill-wise to take up the vacant role. Cost of Change The cost associated with hiring new talent is generally way more than developing talent in-house. The cost of lost time due to training and onboarding, financial cost, and the risk of disturbing group cohesion is just too great. Consider the alternative: You have an employee already in your team with enough experience as well as skills to take up that vacant role. All you need is to change job roles, revise remuneration, and just like that the position is filled. Minimal lost time, slightly higher remunerative cost, and virtually no increase in the risk of disarray in the group. Which one would you prefer? This is the advantage of having a good succession plan. Also read: Succession planning using SWOT analysis Cost of Retaining Talent For the organization to ensure that the best talent stays with them, a good financial remuneration is not always going to solve their problem. Often, people get bored by the monotony of their day to day job. To avoid turning the job into a chore, we have to challenge and inspire employees to learn new skills and grow. Once the employee is motivated to grow, we just have to bear the cost of retaining good talent. This cost is much lower than the cost of replacing talent. Cost of Replacing Talent The costs associated with replacing a talent from outside are huge. Further, if not done correctly, it can even bring a company down to its knees. First, is the cost of time lost in finding a replacement. Next comes the cost of training and acclimatizing the individual in the organization. Add to that, the cost of acquiring talent at short notice, which will surely increase the financial burden. Finally, is the cost associated with the risk of the new member not being able to gel with the colleagues. Employee-Manager Relationship A strong employee-manager relationship is a hallmark of a great organization. The free flow of ideas & needs helps bridge the gaps seen by either of the two. Managers need a good skills management solution to ensure that the succession planning envisioned by the organization is implemented. To get in-depth information please go through our article Best Practices in Skills Management Techniques . A good skills management solution helps in saving time and cost while bringing in accountability. It saves time for the manager in identifying the skill gaps. It also helps in reducing the costs associated with training and development. SkillsDB helps in identifying those gaps, and building competency to develop the best team for the job. Managers can find the skills that are lacking, and assign new skill development programs for the employee. It’s just that easy! How Good Succession Planning Helps A good succession plan ensures that you will always have talent available in-house to step up to any role at short notice. The wheel of learning keeps rotating and developing new talent. To learn more read our article on Succession Planning in 8 easy steps . Companies don’t need to focus on recruiting talent anymore. Adding to that is the likelihood of maintaining group cohesion while minimizing costs. A strong individual growth plan helps managers identify promising talent, look at their skill gaps, and pursue corrective action. Employees value organizations that invest in their personal growth. When their goals align, employees rarely leave, build on their skills, work harder, better, and smarter. When a crisis will arise, as it certainly will one day, employees often step up and lead the way. Further Reading Skills & Competencies, Similar but Different How to best Implement a Competency-Based Training Program FAQ Why do good employees leave organizations? Good employees leave for better opportunities, career stagnation, health reasons, or simply because the modern job market offers abundant options. In the information age, people change jobs and careers multiple times, making some level of turnover inevitable regardless of organizational quality. What is the true cost of replacing an employee? Replacing an employee involves the cost of time lost finding a replacement, training and onboarding expenses, premium compensation for urgent hires, and the risk of the new hire not integrating with the team. These combined costs far exceed what it takes to develop and retain existing talent. How does succession planning reduce hiring costs? Succession planning develops internal talent to fill critical roles, eliminating the need for expensive external recruitment. When a position opens, a prepared employee can step in with minimal lost time, slightly higher compensation, and virtually no disruption to team dynamics. What is Plan A in succession planning? Plan A focuses on working with the people you already have by identifying their skill gaps and investing in their development. As organizational needs evolve, employees are continuously upskilled so they are prepared to take on expanded or elevated roles. What is Plan B in succession planning? Plan B ensures that more than one person is ready, at least skill-wise, to step into any critical role at short notice. This redundancy protects the organization from disruption when turnover inevitably occurs, regardless of how strong your retention efforts are. How does employee boredom impact succession planning? Monotony drives talented people to leave. To retain them, organizations must challenge and inspire employees to learn new skills and grow. A strong succession plan doubles as a retention strategy by giving people clear development paths that keep their work engaging. Why is developing internal talent cheaper than external hiring? Internal development avoids recruitment fees, reduces onboarding time, and preserves team cohesion. The cost of retaining and upskilling a current employee is consistently lower than the combined financial, temporal, and cultural costs of bringing in someone new from outside. How does the employee-manager relationship affect succession planning? A strong employee-manager relationship enables free flow of ideas about development needs and career aspirations. Managers need effective skills management tools to identify gaps, assign development programs, and ensure the succession strategy envisioned by leadership is actually implemented. What tools support effective succession planning? Skills intelligence platforms like SkillsDB help managers identify skill gaps, track employee development, and build competency across teams. These tools save time on gap identification and reduce costs associated with ad-hoc training and development efforts. How does a growth plan help identify future leaders? Individual growth plans give managers visibility into which employees are building the right skills for elevated roles. When employees see the organization investing in their development, they become more engaged and are more likely to step up during critical moments. Can succession planning eliminate employee turnover entirely? No. Some turnover is inevitable no matter how strong your culture or compensation. The goal of succession planning is not to eliminate turnover but to ensure the organization is always prepared with qualified internal candidates ready to fill critical roles when vacancies occur. --- ## A Smarter Way to Do Succession Planning: A Client’s SWOT-Based Strategy URL: https://skillsdb.com/blog/succession-planning During a recent demo with a forward-thinking head of HR, I learned about an unexpected yet brilliantly simple approach to succession planning —one that leverages the classic SWOT analysis framework. His method was so effective, I had to share it. We often think of SWOT (Strengths, Weaknesses, Opportunities, Threats) as a strategic tool for business planning, but this HR leader has embedded it directly into his recruitment, retention, and succession strategies—and the results speak for themselves. Why SWOT Works for Talent Management Succession planning can quickly become overwhelming without structure. According to our client, the best place to start is with clarity—and that’s exactly what SWOT provides. It helps teams quickly distinguish between internal factors (strengths and weaknesses) and external factors (opportunities and threats), creating a well-aligned, actionable plan for talent development. Integrating this approach within a broader workforce planning effort ensures alignment with overall talent goals. He described the process in two simple phases: Phase 1: Assess Internal Strengths & Weaknesses in Succession Planning This phase begins with a candid self-assessment of your current succession planning process. Below are 10 statements. For each, ask yourself: is this generally true for your organization? Be conservative in your ratings—don’t overestimate strengths, especially where uncertainty exists. Internal Assessment Statements We have strong visibility into our succession needs (timing, volume, and critical roles) based on the company’s strategic plan. Our job definitions are clear and complete, leading to well-aligned candidate profiles. We segment our sourcing strategies based on role criticality and market availability. We use a balanced mix of sourcing channels to consistently find the right talent. Our succession planning tools and technologies (like skill & talent tracking software) improve efficiency and accuracy. New hires are engaged and onboarded effectively, minimizing early turnover. Managers are responsive and collaborative throughout the succession planning process. Our business is agile and can quickly adapt to changing talent needs. HR spends a manageable amount of time on administrative succession planning tasks. Leaders actively support and develop employees moving into new roles. Flag any areas where your process falters—these are likely your weaknesses, and identifying them is the first step toward improvement. To effectively manage this process, it’s important to have a clear skills framework in place—often supported by a modern L&D platform—to ensure ongoing learning and development are aligned with succession goals. Phase 2: Evaluate External Opportunities & Threats Next, assess the external talent landscape. Consider how market forces, branding, and geographic dynamics impact your succession strategy. Again, reflect on each of the following statements: External Assessment Statements Our employer brand gives us an advantage in the talent marketplace. The company projects values and messaging that resonate with prospective hires. Our succession planning strategies are realistic and responsive to today’s economic conditions. The supply and demand for our most critical roles are currently balanced. We can reliably source top talent across all required geographies. Use your answers to identify opportunities to capitalize on—and threats that require mitigation. What SWOT Reveals: Turning Insights into Strategy Once you’ve completed both assessments, step back and look at the full picture: Your strengths help you capitalize on external opportunities and guard against threats. Your weaknesses represent strategic vulnerabilities—but they also point to the most immediate areas for improvement. In many cases, improving a single weakness (like inconsistent job definitions or delayed manager involvement) can elevate your overall talent strategy. Addressing these gaps is not just about fixing problems—it’s about unlocking new potential across the board. Final Thoughts: From Framework to Action This approach—shared by a savvy client—showed me just how effective a simple SWOT analysis can be when applied to talent management. It’s a method that balances structure with strategic insight and can be adapted to any organization, large or small. Of course, identifying what’s working and what’s not is just the beginning. To fully act on those insights, organizations may need to dive deeper into the “why” behind weaknesses and explore whether internal efforts or external succession planning experts can help close the gap. If you’re looking to bring clarity and focus to your own succession planning strategy, try this SWOT-based framework. Sometimes, the smartest strategies are the simplest. Related Reads: Employee Goal Management: 5 Things You Must Know Skills & Competencies: Similar but Different How to Best Implement a Competency-Based Training Program FAQ What is SWOT analysis for succession planning? SWOT analysis applied to succession planning evaluates internal strengths and weaknesses of your current talent processes alongside external opportunities and threats in the talent market. It provides a structured, actionable framework for identifying where your succession strategy needs improvement. How does SWOT work for talent management? SWOT separates internal factors (strengths and weaknesses in your processes) from external factors (market opportunities and threats). This clarity helps HR teams build succession plans that capitalize on what is working while systematically addressing vulnerabilities. What should you assess in the internal strengths phase? Evaluate visibility into succession needs, clarity of job definitions, sourcing strategy segmentation, succession planning tools, onboarding effectiveness, manager responsiveness, organizational agility, and HR administrative burden. Be conservative in your ratings to avoid overestimating strengths. What external factors affect succession planning? External factors include employer brand strength, the resonance of company values with prospective hires, alignment of strategies with economic conditions, supply-demand balance for critical roles, and the ability to source talent across required geographies. How do you turn SWOT insights into succession strategy? Strengths help you capitalize on opportunities and guard against threats. Weaknesses reveal strategic vulnerabilities and the most immediate areas for improvement. Often, fixing a single weakness like inconsistent job definitions can elevate your entire talent strategy. Why start succession planning with a SWOT analysis? Succession planning becomes overwhelming without structure. SWOT provides immediate clarity by organizing your assessment into four distinct categories, making it easy to see where you stand and where to focus improvement efforts first. What role does employer brand play in succession planning? A strong employer brand gives organizations an advantage in attracting and retaining talent for succession pipelines. When company values and messaging resonate with prospective hires, the organization can build deeper candidate pools and reduce time-to-fill for critical roles. How do skills frameworks support succession planning? Skills frameworks define what competencies are needed for each role and at what proficiency level. When supported by a modern L&D platform, they ensure ongoing learning and development stay aligned with succession goals, creating a continuous pipeline of prepared internal candidates. Can small organizations use SWOT for succession planning? Yes. The SWOT-based approach is adaptable to any organization size. It balances structure with strategic insight, and even small teams benefit from the clarity it provides around internal capabilities and external talent market dynamics. What are common weaknesses in succession planning processes? Common weaknesses include inconsistent job definitions, delayed manager involvement, poor visibility into succession timing and critical roles, lack of effective tools and technology, and insufficient onboarding that leads to early turnover of successors. --- ## Best Practices for Skills-Based Competency Management URL: https://skillsdb.com/blog/skills-based-management Skills-based competency management isn’t just about mapping skills—it’s about building a sustainable framework that supports your workforce through growth, change, and performance. Executing a successful competency management initiative requires careful planning, clear communication, and strong leadership. In this article, we’ll walk through the best practices for implementing and executing a skills-based competency program, organized into three key phases: pre-implementation, implementation, and deployment. Phase 1: Pre-Implementation – Laying the Groundwork The success of a competency initiative depends on how well you prepare. Pre-implementation is where you define the structure, value, and strategy for your program. 1. Secure Senior Leadership Commitment Leadership buy-in is non-negotiable. Sustained support from senior management ensures the initiative receives attention, resources, and urgency. The best way to secure commitment is by linking skills development directly to business outcomes—whether that’s improved productivity, faster project delivery, or more strategic hiring. ✅ Tip: Use data and pilot results to demonstrate how a competency initiative can help the organization meet its goals. 2. Align HR Policies with Skills Development HR policies must reinforce—not undermine—the program. Rewards, promotions, and internal mobility should be based on performance, not solely on skill evaluations. Policies should encourage skills growth and career development while protecting critical team resources from sudden reassignment. For example, one financial institution implemented a mandatory tenure (24–36 months) before employees could be reassigned. This protected team stability while still promoting career growth. 3. Identify Key Stakeholders and Deliver Value to Each Successful programs bring value to every stakeholder group: Employees need clear incentives to complete skills assessments—like visibility into new career paths or project opportunities. Managers need a way to identify talent, guide development conversations, and align team capabilities with business needs. HR & L&D need accurate data for talent planning, hiring, and training, enabling rapid response to skill gaps. A pharmaceutical company saw its competency program stall because HR wasn’t involved. Once HR became a core partner, the program gained traction and achieved full deployment. 4. Plan for Change Management Early Change management isn’t just a launch event—it’s a continuous communication strategy. Address employee concerns (privacy, evaluations, fairness) and clarify the benefits of participation. Create a safe, development-focused environment. Effective tactics include: Executive memos and benefit statements Consultations with managers and subject matter experts Formation of a skills advisory group Skills training workshops for teams Clear manager accountability and coaching support Integration with familiar job titles and terminology Phase 2: Implementation – Building the Foundation Once leadership support and stakeholder alignment are in place, the implementation phase begins. This is where the architecture of your competency framework is constructed. Key Activities During Implementation Build your skills library : Define core, technical, and leadership skills across the organization. Address title and role alignment : Clarify inconsistencies and standardize definitions. Establish skill proficiency levels and expectations : Use consistent rating scales and observable behaviors. Integrate with existing systems : Link skills data with your HRIS, LMS, and performance tools. Run initial assessments : Collect baseline data to guide future development. Document and report results : Create feedback loops that inform training, mobility, and hiring decisions. 🛠️ Implementation is the phase where operational structure meets strategic vision. Pay close attention to consistency, clarity, and scalability. Phase 3: Deployment – Putting Skills Data to Work In the deployment phase, the program moves from planning into action. Employees complete skills assessments, and the organization begins using the data to drive decisions. Focus Areas During Deployment: Clarify roles and responsibilities : Who owns what in the process—from self-assessments to manager reviews? Train and prepare participants : Help employees understand how to evaluate themselves and use the results constructively. Run formal assessments : Capture initial data and launch gap analysis efforts. Deliver value to all constituencies : Use data to support mobility, staffing, training, and succession planning. Skills data should be used organization-wide to support: Talent development and internal mobility Succession planning and project staffing Training design and workforce planning Recruiting against current and future needs 🧭 One of the most important outputs in this stage is identifying and closing skills gaps. For a deeper dive, check out our blog post: Closing Skill Gaps With Training. Final Thoughts: Build for Sustainability A well-executed skills-based competency management program can become one of the most powerful tools in your talent strategy— if it’s built with the right foundation and maintained with intention. To recap: Secure leadership buy-in by tying skills to business outcomes Align HR policies with development goals Deliver clear value to all key stakeholders Build a scalable, flexible skills architecture Embrace change management as an ongoing effort Use deployment data to drive real organizational value With the right structure and support, your organization can unlock the full potential of its people—and stay ready for whatever comes next. FAQ What is skills-based competency management? Skills-based competency management is a structured framework for mapping, developing, and leveraging workforce skills to support organizational growth, change, and performance. It goes beyond simple skills tracking to build a sustainable system that drives talent decisions across the entire employee lifecycle. What are the three phases of skills-based management implementation? The three phases are pre-implementation (laying the groundwork with leadership buy-in and stakeholder alignment), implementation (building the skills library, proficiency levels, and system integrations), and deployment (running assessments and putting skills data to work for real decisions). Why is senior leadership buy-in critical for competency programs? Sustained support from senior leadership ensures the initiative receives the attention, resources, and urgency it needs to succeed. The most effective way to secure commitment is linking skills development directly to business outcomes like improved productivity, faster delivery, or more strategic hiring. How should HR policies support skills-based management? HR policies must reinforce the program by tying rewards, promotions, and internal mobility to demonstrated performance and skill growth. Policies should also protect team stability, for example by implementing minimum tenure requirements before employees can be reassigned. What value does skills-based management deliver to each stakeholder? Employees gain visibility into career paths and project opportunities. Managers get tools to identify talent and align team capabilities with business needs. HR and L&D receive accurate data for talent planning, hiring, and training to rapidly respond to skill gaps. Why is change management essential for competency programs? Change management is not a one-time launch event but an ongoing communication strategy. Organizations must address employee concerns about privacy, evaluation fairness, and data use while continuously reinforcing the development-focused benefits of participation. What happens during the implementation phase? Teams build the skills library across core, technical, and leadership domains, standardize role definitions and titles, establish proficiency levels, integrate with HRIS and LMS systems, run initial assessments to collect baseline data, and create feedback loops for reporting. How is skills data used during the deployment phase? Skills data drives decisions across talent development, internal mobility, succession planning, project staffing, training design, workforce planning, and recruiting. The most critical output is identifying and closing skills gaps to ensure the workforce meets current and future needs. What are effective change management tactics for this program? Effective tactics include executive memos and benefit statements, manager consultations, formation of a skills advisory group, hands-on workshops for teams, clear manager accountability, and integration with familiar job titles and terminology employees already recognize. What makes a skills-based competency program sustainable long-term? Sustainability requires ongoing leadership support, HR policies aligned with development goals, clear value delivery to all stakeholders, a scalable skills architecture, and continuous change management. Programs that treat implementation as a one-time event rather than an ongoing effort will stall. Why did one company's competency program stall without HR involvement? A pharmaceutical company's program stalled because HR was not involved as a core partner. Without HR's expertise in talent planning, hiring alignment, and training coordination, the program lacked the operational infrastructure needed to gain traction and achieve full deployment. How do you build an effective skills library? Define core competencies shared across the organization, technical skills specific to job families, and leadership competencies for management tracks. Use consistent rating scales with observable behaviors at each level, and address any inconsistencies in job titles and role definitions early. --- ## What Are Competencies? Definition, Types, and Examples URL: https://skillsdb.com/blog/how-to-create-a-competency-definition-for-your-organization A competency is a defined, assessable cluster of skills, knowledge, and behaviors that a person needs to perform a specific part of a job to a required standard. A skill is something you can do. A competency is the job-relevant package of skills, knowledge, and judgment that produces a result, described precisely enough that two managers would rate the same person the same way. Quick reference: What Is a Competency? — the short version of this post, with the one table that matters. I have spent eighteen years helping organizations write competencies, and the same thing happens every time. The first draft is a list of adjectives. "Strong communicator." "Detail-oriented." "Team player." Nobody can assess those, so nobody does, and the framework quietly dies in a shared drive. The definitions that survive are the ones written like engineering specs: an action, an object, an observable standard. This guide covers what competencies are, how they differ from skills and proficiency, the four types most frameworks use, a dozen real examples across roles, and the method for writing definitions that hold up in an assessment. What Is a Competency? A competency describes what a person must be able to do, know, and demonstrate to carry out a critical work function. It sits one level above a skill. "Read a P&ID drawing" is a skill. "Diagnose process faults using P&ID drawings, instrument readings, and shift logs, and escalate per the site's response protocol" is a competency. The competency bundles several skills with the knowledge and judgment to apply them, and it points at an outcome the business cares about. Three properties make something a competency rather than a trait or a task: It is tied to a work outcome. Competencies exist because the job requires a result. If you cannot name the result, you are describing a personality trait. It is observable or measurable. Someone can watch the work, review the output, or test the knowledge and reach a defensible rating. It has levels. A competency is not binary. People perform it at foundational, working, advanced, and expert levels, and those levels are described. Competencies are the foundation of skill specifications. They define what a role demands, they anchor assessments, and they give learning initiatives a target. When they are vague, everything built on top of them wobbles: the assessment becomes an opinion survey, the training plan becomes a course catalog, and the succession plan becomes a list of people the executive team likes. Competencies vs. Skills vs. Proficiency The three terms get used interchangeably, and the confusion costs real money in badly scoped frameworks. Term What it is Example How it is measured Skill A specific, learnable ability Writing SQL queries Often binary or a simple scale Competency A job-relevant cluster of skills, knowledge, and behavior tied to an outcome Building reliable reporting pipelines that finance signs off on Leveled rubric with behavioral anchors Proficiency How well a person performs a skill or competency, right now Level 3 of 5 on reporting pipelines Assessment against level descriptors Skills are the base unit. Competencies organize skills into something a role actually needs. Proficiency is the measurement of either. The full comparison, with worked examples, is in Skills vs. Competencies vs. Proficiency . Types of Competencies Most frameworks sort competencies into four types. The sorting matters because each type is written, assessed, and owned differently. Core competencies Core competencies apply to everyone in the organization regardless of role. They translate company values into observable behavior. At a logistics company, "Safety ownership" is a typical core competency: identifies hazards, stops unsafe work, reports near misses, and follows lockout procedures without being prompted. Core competencies are usually owned by HR and assessed annually. Functional or technical competencies These are the competencies specific to a job family: the engineering competencies, the nursing competencies, the sales competencies. They carry most of the assessment weight because they determine whether someone can do the job. A functional competency for a maintenance technician reads "Perform preventive maintenance on rotating equipment to the OEM schedule with documented completion." Owned by the function leader, assessed by managers and often by evidence. Leadership competencies Leadership competencies describe what the organization expects from people who direct others: setting priorities, developing people, making decisions with incomplete information, holding standards. They are leveled by scope. A first-line supervisor and a vice president both need "Develops people," but the behavioral anchors are different. Behavioral competencies Behavioral competencies cover how work gets done: collaboration, adaptability, customer focus, communication. They are the hardest to write well because they are the easiest to write badly. "Communicates effectively" is not a competency. "Explains technical findings to non-technical stakeholders so they can make a decision without a follow-up meeting" is. Competency Examples Twelve competencies from real frameworks, lightly genericized. Notice the pattern: verb, object, standard, and a result the business would recognize. Data center technician: Critical environment response. Identifies alarms across power, cooling, and fire systems, executes the emergency operating procedure for the affected system, and completes the incident log within the shift. Data center technician: Certification currency. Maintains required vendor and safety certifications, tracks expiry dates, and completes recertification before lapse so the site never operates below its qualified headcount. Nurse: Medication administration. Verifies patient identity, dose, route, and timing against the order, documents administration in the EHR, and escalates discrepancies before administering. Nurse: Patient handoff. Delivers structured shift handoffs covering condition, pending results, and risks, so the receiving nurse can act without re-reading the chart. Project manager: Scope control. Documents baseline scope, runs a change process that quantifies cost and schedule impact, and secures sponsor sign-off before absorbing any change. Project manager: Risk management. Maintains a risk register with owners and triggers, reviews it at each stage gate, and activates mitigations before risks convert to issues. Sales engineer: Technical discovery. Maps a prospect's current architecture, constraints, and success criteria in the first two calls and produces a solution outline the account executive can price. Sales engineer: Proof-of-concept delivery. Scopes, builds, and demonstrates a proof of concept against agreed success criteria within the committed timeline. Line supervisor: Shift planning. Assigns qualified operators to every station using the current skills matrix, covers absences without dropping below required certification levels, and records the plan before shift start. Line supervisor: Quality escalation. Recognizes out-of-spec conditions, stops the line per the control plan, and initiates containment and root-cause steps within the documented window. Financial analyst: Variance analysis. Explains budget-to-actual variances with quantified drivers and a recommended action, delivered by the close calendar. Software engineer: Production readiness. Ships changes with tests, monitoring, and rollback paths, and can explain the failure modes to an on-call peer. Each of these can be assessed by watching the work, reviewing artifacts, or testing knowledge. None of them contains the word "good." How to Write a Competency Definition The method has not changed in the years I have been teaching it. It works because it forces precision. Start with a present-tense action verb. Diagnoses, builds, verifies, escalates, documents. The verb tells you what to observe. Give the verb an object. "Verifies patient identity." "Documents baseline scope." Verb plus object is the skeleton of the definition. Add the standard. Against what? By when? To whose satisfaction? "Before administering." "Within the shift." "So finance signs off." The standard is what separates a competency from a wish. Base it on performance, not attendance. Completing a course is not a competency. Doing the work the course taught, to the standard, is. Strip every evaluative adjective. Good, strong, effective, appropriate, successful. If the word cannot be measured, it does not belong. Replace it with the observable behavior you actually mean. A worked example. First draft: "Strong spreadsheet skills." Second draft: "Uses standard formulas and functions, formats and modifies content, and builds spreadsheets, charts, and graphs." Final draft: "Builds spreadsheet models with documented formulas and validation checks that a reviewer can audit without the author present." The final version names the object, the standard, and the result. It can be assessed by opening the file. The deeper craft, including how to handle knowledge versus behavior and how to avoid definitions that only the author understands, is in The 4 Pillars of Writing Competency Definitions . Competencies vs. learning goals The definitions above are not learning objectives, and confusing the two is a common early mistake. A learning goal describes what a learner should be able to do at the end of a course. A competency describes what the job requires, regardless of how the person acquired it. Learning goals are the path. Competencies are the destination that validates the path was worth walking. A spreadsheet course has the goal "construct formulas using relative and absolute references." The competency it serves is the auditable model above. Competency Frameworks and Models A single competency is useful. A competency framework is where the value compounds. The framework organizes competencies by role and job family, assigns the required proficiency level for each, and connects them to hiring, assessment, development, and succession. It is the structure that lets an organization say, with evidence, "these 40 people are qualified for that work, these 12 are one level away, and here is the training that closes the gap." Frameworks are built in one of a handful of ways: adapting a published model, deriving competencies from top performers, working backward from strategy, or a hybrid. Each has trade-offs in speed, ownership, and fit. The comparison is in 4 Types of Competency Models . The one rule that holds across all of them: write the framework in your organization's language. Imported taxonomies look complete in a demo and wither once real managers have to rate real people against words they never use. How Competencies Are Assessed A competency definition is only as valuable as the assessment behind it. Assessment turns the definition from a document into data: this person, this competency, this level, this date, this evidence. Three things make competency assessment credible. First, a leveled proficiency scale with behavioral anchors for each level, so "3" means the same thing across managers and sites. How to build those scales is covered in Proficiency Levels: Scales, Examples, and How to Define Them . Second, more than one rater. Self-assessment paired with manager assessment surfaces the gaps in perception, and the delta is where the useful coaching conversation lives. Third, evidence. A rating with a reason attached, whether an observed task, a work sample, or a test, holds up in a promotion discussion and in an audit. This is the point where competencies stop being an HR artifact and become operational infrastructure. In SkillsDB, competencies are a primitive: they live in the competency framework , they carry leveled proficiency scales, and every proficiency assessment writes a dated, evidenced score against them. The definition, the level, and the assessment are one record, which is what makes gap analysis, staffing, and succession answerable with data rather than memory. Definitions Are the Foundation Every downstream workforce decision inherits the quality of the competency definitions underneath it. Write them as observable behaviors with standards and outcomes, level them, and assess against them with evidence. Skip that discipline and the framework becomes a vocabulary list. Apply it and competencies become the most useful data an organization holds about its own capability. FAQ What is a competency, in simple terms? A competency is a job-relevant bundle of skills, knowledge, and behavior that a person needs to produce a specific result at work. It is written as an observable action with a standard, so it can be assessed and developed rather than guessed at. What is the difference between a skill and a competency? A skill is a single learnable ability, such as writing SQL. A competency groups related skills with the knowledge and judgment to apply them toward a work outcome, such as building reporting pipelines that finance relies on. Skills are the units; competencies are how a role organizes them. What are the main types of competencies? Most frameworks use four types: core competencies shared by everyone, functional or technical competencies specific to a job family, leadership competencies for people who direct others, and behavioral competencies that describe how work gets done. Each type is written and assessed differently. How do you write a competency definition? Start with a present-tense action verb, give it a specific object, add the standard the work must meet, base it on performance rather than course completion, and remove every evaluative adjective. The result should be something a manager can observe or test and rate consistently. Can you give an example of a competency definition? For a line supervisor: "Assigns qualified operators to every station using the current skills matrix, covers absences without dropping below required certification levels, and records the plan before shift start." It names the action, the object, the standard, and the business result. How are competencies assessed? Competencies are assessed against a leveled proficiency scale with behavioral descriptions for each level, ideally by more than one rater and with evidence attached to the rating. Self-assessment paired with manager assessment, backed by observed work or test results, produces data that holds up in development, promotion, and audit conversations. --- ## New Hire Training Plans Using Competency Modeling URL: https://skillsdb.com/blog/new-hire-training New hire training the startling truth for companies: 20% of all employees, as wells as 40% of those who receive bad (or no) new hire training leave inside the 1st year of employment. When personnel leave, it costs you. In this article we are going to talk about new hire training as it pertains to job roles that they perform. Most companies already know how to get a new hire their HR information. We are going to teach you how to train them for the job they are taking on using a competency-based training program. New hire training is among the most crucial components of a training development program. It is the main factor that increases the skill set of each staff member. A focused, job role training program can take new hires, current employees, as well as your whole business to a higher level. The reason why new hire job role training programs stand out against more common training programs is because they specifically focus on the skills required to broaden, as well as increase an organization’s core skill sets. Together with an overall competency development plan, this provides the most effective return on training investment for a business. A well-structured competency management platform can help track and manage this growth efficiently. 4 Steps for Creating a Successful New Hire Training Program Developing a training program is not as challenging as you may think provided that you split it down into logical steps. The ADDIE technique is particularly helpful whenever beginning a training program completely from scratch: Analysis: Evaluate what your staff must know to be able to successfully perform their jobs. Design: Figure out what your new hire training program may be like. Development: Create techniques, resources, and materials which will be inside your training program. Implementation: Determine the new hire training program will be put into place Evaluation: Get opinions to help you determine if your new hire training program met you as well as your employees’ requirements. Evaluate Your Staff & the Skills Necessary for the Work Investigation is a particularly important element of successfully developing a new hire training program. You will be resolving questions like: What do your staff have to know? What do your staff know already? Just how do your employees learn most effectively? What do I want from my team? What do my staff members expecting? What kind of instruction satisfies each of these requirements? Do I possess skilled people to carry out the new hire training? Developing Your Competency Framework – Linking Skills to Company Objectives Know precisely what each specific job role calls for: Create a competency framework in which you discover gaps in staff effectiveness. What caused this gap? Was it solely dependent on deficiency of the employee’s skills and training, or may blame can be put on the applications as well as the systems they had to work with? In order to develop a new hire training program, you need to be certain those tools and systems are in order. All the instruction in the world won’t boost staff efficiency and outcomes if what they now have to work with is broken. Design the New Hire Training Program It is now time to develop a new hire job role training framework. Along with all levels of management, it is essential to define a strategy that will work for your business. Be sure to create a new hire training framework that is in-line with your competency development objectives. When building a framework for job role training, bear in mind: Simplicity of use– If the program is difficult to understand, employees may get discouraged. Motivation – If new hires can’t understand the end goal or don’t recognize how the program is benefiting them, they won’t push themselves to satisfy the desired goals. They have a life – For most companies, employees are working full time as well as learning new skills after hours. This may put a stress on staff members. It is essential to have an equilibrium in mind whenever creating your new hire training framework. Using a robust training platform for employees can make it easier to manage schedules, track progress, and engage learners with ease. Create Your Training Materials When you know how your instruction will look, you can certainly find materials to flesh out your education goals describe within a variety of places: There are numerous approaches to put into practice Job Role training programs such as, but not limited to, one-on-one training sessions, seminars, e-courses, personal and self-paced, in a team environment using an instructor, and far more. Keep in mind that whenever adults begin a training program you will find two considerations: Each person comes with different degrees of understanding of the subject. Each person has unique learning styles along with all of the other, non-work associated stuff taking place in their lives. They are likely to learn at various paces. Conclusion: Examine with Employee Measurements Figure out how effective your new hire training program is using a simple technique: ask. Utilize a questionnaire that allows for privacy, and consider delivering the survey several months after the training. Seek out progress in staff member work. Increased employee effectiveness will always positively affect your company’s performance. You might evaluate employee improvement by contrasting how they performed before and after training. You can use tools to help this process along as well. At SkillsDB we allow employees to choose from recommended development plans based upon their current skill levels and where they want their career path to take them. This level of insight supports a more tailored and effective competency based training program. FAQ Why is new hire training critical for retention? Twenty percent of all employees and 40% of those who receive poor or no training leave within their first year. Structured new hire training directly reduces early turnover and the significant costs associated with replacing employees. What is competency-based new hire training? Competency-based new hire training focuses specifically on the skills required for an employee's job role rather than generic orientation content. It maps training to the competencies needed for each position, delivering a stronger return on training investment. What is the ADDIE method for training programs? ADDIE stands for Analysis, Design, Development, Implementation, and Evaluation. It provides a structured, step-by-step approach for building training programs from scratch, ensuring each phase builds logically on the previous one. How do you evaluate skills needed for new hires? Start by identifying what employees need to know, what they already know, and how they learn best. Create a competency framework that maps required skills to each role and identifies gaps between current capabilities and job requirements. What should a new hire training framework include? A training framework should be simple to use, clearly communicate the end goal to new hires, and respect work-life balance. It must align with your organization's competency development objectives and be designed in collaboration with management. How do different learning styles affect new hire training? Every new hire brings different levels of subject knowledge and unique learning preferences. Effective training programs accommodate these differences through varied formats like one-on-one sessions, e-courses, seminars, and self-paced learning options. How do you measure new hire training effectiveness? Use anonymous employee surveys distributed several months after training, track progress in employee performance metrics, and compare pre-training and post-training results. Direct feedback and measurable skill improvement are the clearest indicators of program success. Why do job role training programs outperform generic training? Job role training programs focus specifically on the skills required to strengthen an organization's core capabilities. Combined with a competency development plan, they deliver a higher return on training investment than broad, one-size-fits-all approaches. How does a competency framework support new hire training? A competency framework identifies gaps in staff effectiveness by mapping required skills to each job role. It provides the foundation for designing targeted training that addresses actual skill deficiencies rather than assumed needs. How does SkillsDB support new hire development plans? SkillsDB allows employees to choose from recommended development plans based on their current skill levels and career goals. This personalized approach ensures new hires receive training that is directly relevant to their role and growth trajectory. --- ## How to Create a Skills Matrix: The Complete Guide URL: https://skillsdb.com/blog/develop-a-skills-matrix A skills matrix can help better utilize current staff today and into the future, while giving better information about recruiting needs. What is a skills matrix? A skills matrix, or competency matrix, is an instrument to map essential, as well as preferred, skills for a team or project. This can be a grid which visualizes readily available capabilities along with competencies inside of a workforce. Therefore, it is a crucial resource for virtually every data-driven resourcing decision. Many organizations also refer to it as a training matrix when used for employee development planning. The finished skills matrix visualizes the skillsets needed and the relevant skills which are readily available within the workforce, as well as the skillsets lacking. This difference between these is the skills gap. What is a skills matrix utilized for? A skills matrix enables you to measure essential skills for any task or project. To effectively employ a skills matrix, you should develop a breakdown of the skillsets needed to finish a project effectively. This exercise establishes critical team skillsets, as well as required skills and/or competencies. For instance, if an information technology analytics job needs business acumen, IT skills, data analytics abilities and reporting abilities, you have to verify which individual within the workforce has which skills. When a particular skill is lacking, it is simple to hire a staff member with all the related skills to add to workforce. Accomplishing this prior to the beginning of a project, it enables a better result. When you have to perform a skills investigation in retrospect, it usually signifies an unsuccessful project. Steps to develop a competency matrix Identify the pertinent skills for the task Identify the pertinent skills for a project or team Skill matrices are typically developed by a project manager to boost team effectiveness and should assess which skills are absent to prevent the workforce from missing due dates, internal discord or other cost afterwards Create a good evaluation of the applicable skills and competencies required to finish a project Evaluate team members for their existing skill levels Assess the team for their existing skill levels. Sending a skills survey is the best way to capture this, or via proficiency tests for the individual and their immediate peers and supervisor You need to know each person’s expertise. For example, you can group skills into five categories: None. No knowledge or awareness. Needs/wants training. Basic. Applies the knowledge/skill in simple and somewhat difficult situations, requires close and frequent guidance. Intermediate. Generally applies the knowledge/skill in difficult situations, requires occasional guidance. Advanced. Consistently applies the knowledge/skill in considerably difficult situations with little or no guidance. Expert. Consistently & proactively applies the knowledge/skill in exceptionally difficult situations, acts as a key resource & role-model advising others. A 180-degree feedback tool can be used to analyze an employee’s skills by requesting with an immediate supervisor. Identify a person’s desire for doing the tasks requested of them People want to like the job they are doing Your skills matrix may demonstrate a person is qualified in a vital task, but if the individual is reluctant to perform the task, you may still reach a dead end Include information within the skills matrix and take action You now understand both the needed and the available competencies, now you can develop the skills matrix. This matrix enables you to envision what skills are available and what skills are absent. You can start with a skills matrix template to simplify the process and ensure consistency. Download a free skills matrix here . Utilizing the skills matrix, it is easy to see a team’s strengths and weaknesses Even more sophisticated would also include growth to identify people who want to strengthen their skills beyond their current level. Incorporating a skill framework ensures the matrix is aligned with long-term talent development and training goals. Conclusion A skills matrix can help better utilize your current team today and into the future. Today, more than ever, there is a scarcity of people with the right skills in the right roles. Skills matrices help clarity roles and weaknesses. FAQ What is a skills matrix? A skills matrix is a grid that maps the essential and preferred skills for a team, project, or workforce. It visualizes available competencies alongside missing ones, making the skills gap immediately visible for data-driven resourcing decisions. What is a skills matrix used for? A skills matrix helps you identify which team members have which skills before a project begins. It enables better staffing decisions, reveals gaps that require hiring or training, and prevents project failures caused by unidentified skill shortages. How do you develop a skills matrix step by step? Start by identifying the skills required for the project or team. Then assess each team member's current skill level, gauge their interest in performing specific tasks, and populate the matrix to visualize strengths, gaps, and development opportunities. What skill proficiency levels should a matrix include? A common five-level scale includes None, Basic, Intermediate, Advanced, and Expert. Each level describes increasing independence and complexity of application, from needing close guidance to acting as a key resource and role model for others. Why does employee interest matter in a skills matrix? A skills matrix may show someone is qualified for a task, but if they are reluctant to perform it, productivity suffers. Factoring in interest and motivation ensures you assign people to work they are both capable of and willing to do. What is the difference between a skills gap and a skills matrix? A skills matrix is the tool that maps available competencies against required ones. The skills gap is the difference it reveals between what your team can do today and what they need to be able to do for success. How does a skills matrix improve hiring decisions? By clearly showing which skills are missing from your current workforce, a skills matrix lets you target recruitment toward specific competencies. This prevents redundant hires and ensures new team members fill actual capability gaps. Can a skills matrix be used for employee development? Yes. When combined with a skill framework, the matrix identifies where employees can grow beyond their current level. Organizations use this data to create targeted training plans aligned with long-term talent development goals. What is a 180-degree feedback tool in skills assessment? A 180-degree feedback tool gathers skill evaluations from the employee and their immediate supervisor. It provides a more balanced view of competency levels than self-assessment alone, helping populate the skills matrix with more accurate data. How does SkillsDB help build a skills matrix? SkillsDB provides a centralized platform to map skills across your workforce, assess proficiency levels, identify gaps, and connect the matrix to career pathways and development plans. It replaces static spreadsheets with a dynamic, always-current view. --- ## Succession Planning: Why Every Organization Needs a Strategy URL: https://skillsdb.com/blog/succession-planning-in-8-easy-steps Could your employees answer the question: “What is the succession planning strategy at our company?” They could—if you’ve discussed it with them. And you could, if you’ve actually developed one for your organization. Succession planning isn’t just a checkbox activity—it’s a critical strategy that builds confidence for employees and ensures long-term stability for your company. For employees, it answers the “what’s next?” question. For managers and leadership, it’s a proactive approach that aligns talent development with future leadership needs. What Is Succession Planning? Succession planning is the process of identifying and developing future leaders at all levels of the organization. It ensures business continuity when employees retire, resign, are promoted, become ill—or even pass away. Rather than reacting to a crisis, organizations with strong succession plans are ready for the future. They prepare high-potential employees to step into critical roles through structured development, mentoring, and visibility into advancement opportunities. A modern skills development platform can support this by tracking capabilities, aligning employee growth with leadership goals, and enabling data-driven decision-making. Why Succession Planning Matters Succession planning often falls by the wayside—but it shouldn’t. It’s not about reacting to loss. It’s about creating a controlled, strategic process that builds organizational strength from within. Done well, it results in: Greater employee retention Stronger leadership pipelines Reduced hiring costs Improved morale and clarity around career growth 8 Succession Planning Best Practices Whether you’re a small business or a global enterprise, these best practices can help you launch or strengthen your succession strategy: 1. Be Proactive It takes time to prepare someone for a leadership role. Don’t wait until a position is vacant—start early. Even if you don’t anticipate turnover, grooming someone now builds a safety net for the future. 2. Broaden Your Perspective Your next leader may not be the most obvious choice. Look beyond job titles. Identify people who demonstrate the core skills, values, and potential to succeed—regardless of their current role. 3. Cultivate a Culture of Growth Expose future leaders to strategic conversations and business-wide goals. Involve HR and your board in the planning process to ensure alignment. Leadership development should be embedded in your culture, not treated as a siloed initiative. 4. Give Frequent, Constructive Feedback Track performance continuously—not just during annual reviews. Document top-performer behaviors, project outcomes, and leadership indicators. This creates a living record you can refer to when evaluating succession candidates. 5. Invest in Development Offer top performers opportunities like: Mentorships Job shadowing Coaching Cross-functional projects Remember: great leaders need more than technical skills. Prioritize soft skills like communication, adaptability, and diplomacy. 👉 Looking to build better growth paths? Read: How to Create Employee Development Plans That Work 6. Conduct a Skills Audit A skills audit helps you identify current capabilities and gaps. When someone leaves, you’ll be able to quickly search for qualified internal candidates—or understand what hiring is required. 📘 More on this: Read our article on skills audits 7. Run a Pilot Test Let potential successors take the lead during vacations or on special projects. This “test run” provides valuable experience for them—and valuable insight for you into their readiness. 8. Align Succession Planning With Hiring Strategy Once you’ve identified internal successors, turn your focus to the gaps. Use those insights to shape external hiring strategies, especially for niche or high-risk roles. The Bottom Line: Prepare for the Future Succession planning is more than a retention tool—it’s a commitment to the long-term health of your organization. By identifying future leaders and supporting their growth, you protect business continuity and increase employee engagement. When paired with workforce planning and powered by a skills development platform, succession planning becomes a strategic advantage—not just a contingency plan. Start early. Build deliberately. Lead confidently. FAQ What is succession planning? Succession planning is the process of identifying and developing future leaders at all levels of an organization. It ensures business continuity when employees retire, resign, are promoted, or are otherwise unavailable to fill critical roles. Why does succession planning matter for organizations? Organizations with strong succession plans experience greater employee retention, stronger leadership pipelines, reduced hiring costs, and improved morale. It transforms leadership transitions from reactive crises into controlled, strategic processes. When should you start succession planning? Start as early as possible. It takes significant time to prepare someone for a leadership role, and waiting until a position is vacant creates risk. Proactive grooming builds a safety net even when turnover is not anticipated. How do you identify potential successors in your organization? Look beyond job titles and obvious candidates. Identify people who demonstrate core skills, values, and leadership potential regardless of their current role. A skills audit helps surface qualified internal candidates who might otherwise be overlooked. What is a skills audit in succession planning? A skills audit evaluates your workforce's current capabilities and identifies gaps. When someone leaves a critical role, it enables you to quickly search for qualified internal candidates or understand exactly what external hiring is needed. How do you develop employees for future leadership roles? Invest in mentorships, job shadowing, coaching, and cross-functional projects for high-potential employees. Prioritize soft skills like communication, adaptability, and diplomacy alongside technical capabilities to build well-rounded future leaders. What is a pilot test in succession planning? A pilot test lets potential successors take the lead during vacations or on special projects. This trial run provides practical leadership experience for the candidate and gives you valuable insight into their readiness for the role. How should succession planning connect to hiring strategy? Once you have identified internal successors, focus external hiring on the remaining gaps. Use insights from your succession plan to shape recruitment strategies, especially for niche or high-risk roles that lack internal candidates. What role does feedback play in succession planning? Continuous performance tracking, not just annual reviews, creates a living record of top-performer behaviors and leadership indicators. This documented history gives you objective data when evaluating succession candidates against role requirements. How does a skills platform support succession planning? A skills development platform tracks employee capabilities, aligns individual growth with leadership goals, and enables data-driven decision-making. It turns succession planning from a subjective exercise into a strategic, measurable process. What are the 8 succession planning best practices? Be proactive, broaden your perspective on candidates, cultivate a growth culture, give frequent feedback, invest in development, conduct a skills audit, run pilot tests, and align succession planning with your hiring strategy. --- ## How to Build a Skills Competency Framework That Actually Works URL: https://skillsdb.com/blog/skills-competency-frameworks-demystified A skills competency framework helps your organization define the specific skills, behaviors, and attitudes employees need to succeed in their roles. But how do you actually know if your employees are competent in their tasks? And more importantly—how do you decide what to measure? Many organizations rely on training or personal traits as indicators of job success. But a more strategic, organization-wide approach is to align employee performance with business goals through a skills competency framework . What Is a Skills Competency Framework? A skills competency framework is a structured model that defines the essential knowledge, skills, and behaviors required for success in each role. It makes expectations clear and measurable and connects individual performance with organizational objectives. When implemented well, this framework benefits the entire business. It enables: More effective hiring and onboarding Targeted employee development and training Clear career paths and promotion criteria Better performance evaluations Proactive succession planning Stronger change management Most modern organizations pair their framework with a competency management platform to keep information current, centralized, and actionable. Why Your Company Needs One By aligning individual effectiveness with business objectives, your organization gains: Clarity around role expectations Consistency in evaluating performance Focus in training and development investments Insight into skills gaps and future hiring needs Engagement from employees who understand how their work matters How to Build a Skills Competency Framework Developing a robust framework takes effort, but the payoff is a more agile, effective organization. Here’s how to do it: Step 1: Define the Purpose Start by clarifying your goals. Ask: Why are we building this framework? How will it be used? (e.g., hiring, development, succession planning?) Who should be involved? Your answers will shape the scope of your framework. A hiring-focused framework will differ from one meant to support company-wide performance management. Step 2: Build the Right Team Form a diverse project team with representatives from HR, leadership, and departments across the company. This ensures broad input and helps with future adoption. Also consider: Who understands the job roles best? Who will maintain and evolve the framework over time? Step 3: Gather Data on Roles The quality of your framework depends on the quality of your insights. Use multiple methods to gather information about each job: Observation – Watch employees perform their roles Interviews – Talk to employees, managers, and HR Surveys – Ask targeted questions about tasks and success factors Job analysis – Break down responsibilities into specific actions and outcomes Look for common patterns in how success is achieved across roles. Step 4: Group and Define Competencies Once you’ve collected enough data: Organize behaviors into themes – e.g., technical skills, communication, decision-making Create subcategories – Break large themes into focused clusters Define competencies – Give each cluster a clear name and description Refine language – Ensure each competency is specific, measurable, and relevant Competencies should be tailored to roles. For example, financial skills may be critical for managers but irrelevant for frontline customer service staff. Step 5: Validate and Finalize the Framework Test the framework with stakeholders and potential users. Adjust language or structure as needed based on feedback. Ensure the competencies: Are understandable Apply consistently across similar roles Align with company strategy Step 6: Implement and Communicate Successful implementation depends on communication. Help employees understand: Why the framework was created How it benefits them How it will be used (in evaluations, development planning, etc.) Use your competency platform to make the framework easily accessible and to link it with your performance, learning, and recruitment systems. Best Practices for Long-Term Success Use relevant, role-specific competencies – Avoid “one-size-fits-all” models Review regularly – Update the framework to reflect changes in business strategy or job roles Link to training – Use the framework to guide targeted development programs Align with talent strategy – Integrate it with succession planning and hiring plans Involve employees – Get feedback and input from those who live the roles every day Conclusion: From Strategy to Action A well-designed skills competency framework gives your organization the tools to evaluate, develop, and retain top talent. It connects day-to-day work with broader goals and ensures that every employee understands what success looks like. Yes, it takes effort—but the payoff is worth it: better hiring, stronger development, more confident leaders, and a culture of high performance. FAQ What is a skills competency framework? A skills competency framework is a structured model that defines the essential knowledge, skills, and behaviors required for success in each role. It makes expectations clear and measurable and connects individual performance with organizational objectives. Why does my company need a competency framework? A competency framework provides clarity around role expectations, consistency in evaluating performance, and focus in training investments. It also reveals skills gaps, informs hiring decisions, and increases employee engagement by showing how individual work contributes to business goals. How do you build a skills competency framework? Define the framework's purpose, assemble a cross-functional team, gather data on roles through observation and interviews, group and define competencies, validate with stakeholders, and implement with clear communication. Each step builds on the previous one. What data methods help define role competencies? Use observation to watch employees perform their roles, interviews with employees and managers, targeted surveys about tasks and success factors, and formal job analysis that breaks responsibilities into specific actions and outcomes. Multiple methods produce the most accurate results. How do you group and define competencies effectively? Organize observed behaviors into themes like technical skills, communication, and decision-making. Break large themes into focused subcategories, give each a clear name and description, and refine the language to ensure each competency is specific, measurable, and role-relevant. Should competencies be the same across all roles? No. Competencies should be tailored to specific roles. Financial skills may be critical for managers but irrelevant for frontline staff. A one-size-fits-all approach undermines the framework's usefulness and credibility with employees. How do you validate a competency framework before launch? Test the framework with stakeholders and potential users, then adjust language and structure based on feedback. Ensure competencies are understandable, apply consistently across similar roles, and align with company strategy before rolling it out organization-wide. How should you communicate a new competency framework? Help employees understand why the framework was created, how it benefits them personally, and how it will be used in evaluations and development planning. Transparency drives adoption and reduces resistance to the new system. What are best practices for maintaining a competency framework? Review and update the framework regularly to reflect changes in business strategy and job roles. Link it to training programs, integrate it with succession planning and hiring, and involve employees in providing feedback to keep it relevant. How does a competency framework support succession planning? By clearly defining what success looks like in each role, a competency framework identifies which employees are ready for advancement and where development gaps exist. This makes succession decisions data-driven rather than based on gut feeling. What role does a competency platform play in framework management? A competency management platform keeps your framework centralized, current, and actionable. It links competencies to performance systems, learning programs, and recruitment workflows so the framework stays a living tool rather than a static document. How does a competency framework improve hiring decisions? It provides clear, role-specific criteria that hiring managers can evaluate candidates against. This reduces subjective decision-making, ensures consistency across interviewers, and helps identify candidates who will genuinely succeed in the role. --- ## What Is Goal Management — And Why It’s Essential for Business Success URL: https://skillsdb.com/blog/employee-goal-management Employee goal management is much more than just setting targets and evaluating performance. Done well, it becomes a strategic tool for developing talent, building capabilities, and aligning your workforce with company objectives. At its core, goal management helps employees grow their skills, knowledge, and abilities—while helping the business achieve measurable results. Today, leading organizations use skills management platforms to facilitate this process, ensuring that employee capabilities are tracked, updated, and aligned with evolving goals. How Goal Management Powers Strategic HR Effective goal management gives HR leaders a practical path for aligning talent with business needs. For example, to improve frontline service delivery, companies can: Map the skills of top performers Set role-specific goals based on those skills Track progress and performance over time This method ensures that your best people set the benchmark for success—and others can be coached, trained, and developed toward that same standard. More importantly, with a structured skills and goal management system in place, you gain a clear, objective view of your workforce. You can: See where critical skills exist Identify gaps Evaluate readiness for new roles Deliver training that matches actual needs Platforms that support competency models and ongoing skills assessments make this process scalable and data-driven. The Link Between Employee Goals and Company Strategy To be truly effective, employee goals must directly connect to your organization’s broader objectives. This is where many traditional performance management systems fall short—they set goals in isolation. High-performing organizations make goal alignment a regular practice, not a once-a-year exercise. They encourage managers and executives to: Revisit company goals often Adjust priorities based on changing conditions Connect individual goals with departmental and organizational outcomes Without this alignment, employees might hit their personal goals but fail to contribute meaningfully to business success. Goal Management is a Continuous Process Goal management isn’t “set it and forget it.” It requires ongoing conversations between managers and employees—conversations that include: Regular feedback Coaching and mentoring Progress reviews and adjustments This ongoing dialogue helps keep individual performance aligned with business needs and allows for real-time adjustments as priorities shift. Put Employee Skills to Work Organizations striving to meet strategic goals need a smarter way to manage their people. Skills measurement platforms provide the foundation for: Improving hiring decisions Creating accountability for growth Maximizing performance with leaner teams Turning insights into action When employees know that their skills are being measured—and when they understand how those skills connect to their goals and the company’s goals—they are more engaged, more focused, and more productive. As the old saying goes: “ What gets measured gets managed. And what gets managed gets better. ” Goal management, when paired with effective skills tracking, brings this principle to life. Final Thoughts Goal management isn’t just an HR process—it’s a business imperative. By linking employee development to business outcomes, you create a culture of accountability, clarity, and progress. And by leveraging a smart, integrated platform to track both goals and skills, you ensure your team is always ready to perform, adapt, and grow. FAQ What is employee goal management? Employee goal management is the strategic process of setting, tracking, and aligning individual employee targets with broader business objectives. It goes beyond annual reviews to include ongoing coaching, feedback, and skills development that drives measurable results. How does goal management connect to company strategy? Effective goal management directly links individual employee goals to departmental and organizational outcomes. Without this alignment, employees may hit personal targets but fail to contribute meaningfully to overall business success. Why is goal management a continuous process, not annual? Business priorities shift throughout the year, and goals set once in January may be irrelevant by June. Continuous goal management through regular feedback, coaching, and progress reviews keeps individual performance aligned with current business needs. How do skills assessments improve goal management? Skills assessments provide objective data on where employees stand today, making it possible to set realistic, targeted goals. They reveal capability gaps, evaluate readiness for new roles, and ensure training investments match actual needs rather than assumptions. How does goal management power strategic HR decisions? By mapping top-performer skills and setting role-specific goals based on those benchmarks, HR leaders gain a clear view of workforce capabilities. This enables data-driven decisions about training, promotions, team composition, and resource allocation. What happens when employee goals are set in isolation? Goals set without connection to business strategy become meaningless checkboxes. Employees may achieve their individual targets while the organization fails to advance its priorities. Alignment between personal goals and company objectives is what makes the process valuable. How does skills tracking improve employee engagement? When employees know their skills are being measured and understand how those skills connect to their goals and the company's goals, they become more engaged, focused, and productive. Visibility into progress creates accountability and motivation. What role do managers play in employee goal management? Managers are essential for ongoing conversations that include regular feedback, coaching, mentoring, and progress adjustments. They ensure goals stay relevant as priorities shift and provide the support employees need to achieve their targets. How does a skills management platform support goal management? A skills management platform tracks capabilities, identifies gaps, and connects skill development to business goals in a single system. It makes the entire goal management process scalable, data-driven, and actionable across the organization. What measurable outcomes does effective goal management produce? Effective goal management leads to improved hiring decisions, greater accountability for growth, maximized performance from leaner teams, and the ability to turn workforce insights into concrete action. It directly impacts both employee development and business results. --- ## Competency Management Missteps URL: https://skillsdb.com/blog/competency-management-missteps Competency management missteps can sometimes be daunting. Implementing a new system in your organization can be a tedious process. There can be setbacks along the way, but have no fear, not only can we guide you in simple steps to set up your system , but we want you to learn from the common mistakes that we’ve seen. Here are five of the most common competency management missteps. “It’s fine to celebrate success but it is more important to heed the lessons of failure.” Bill Gates Competency Management Misstep 1: Biting off more than you can chew “An entrepreneur tends to bite off a little more than he can chew hoping he’ll quickly learn how to chew it.” Roy Ash, Litton Industries There’s nothing wrong with being ambitious or following a “sink or swim” approach but when it comes to implementing a new competency management system it’s risky to try and do it all at once. One of the top competency management missteps is going too big, too fast. Think of rolling out your competency management system as a fine multi-course dinner, rather than an all-you-can-eat buffet. You want a well-curated, sensical approach that is unveiled piece by piece, rather than a disordered smorgasbord that will leave your HR and management teams feeling like they have a massive mess to clean up. It is vital to implement your new competency management system in step by step measures that make sense for your company. Start with a smaller project that can be designed and implemented in a relatively short period. You can then use this as a model in future projects for what worked and what might need some more fine-tuning. Also remember to keep this first step simple, focused and well-defined. Identify key roles, job duties and employee skills that are most vital to your company initially. From there you can build upon your successes and avoid further competency management missteps. This is where a scalable competency management platform can make a significant difference, helping you gradually align systems across departments. Competency Management Misstep 2: Competency complexity “Life is really simple, but we insist on making it complicated.” Confucius One of the most common missteps in competency management is an abuse and misuse of language and logic. Some companies can create too many levels, while others simply create too many competencies. Still, others can have run-on competencies and redundant competencies. All of these missteps overcomplicate, confuse and muddle competency management. Your organization will want to identify the most essential competency profiles and from there, only the most necessary competency lists. Adding too many competencies will drown your system in a flood of complication. In addition to a simplified number, simplified words are needed. Many competencies can be misconstrued through poorly worded, jargon-filled, unclear language. Be simple, be specific and avoid repeating synonymous competencies. Management Misstep 3: Not tailoring your system to your company “By changing nothing, nothing changes.” Tony Robbins Competency management is not a one-size-fits-all solution. If you want the most out of the information and analytics of your system, it must be tailored to meet your company’s needs. You’ll need to look both inside and outside your organization for meaningful data that can power your competencies. You don’t have to reinvent the wheel, however. There are many sources within your industry, governmental agencies and even in your own organization that can lead you to the specific competencies that matter to you. Once identified and adapted to an organization’s needs, key skills and competencies can actually lead to major growth, adaptations and saving money for many companies. Organizations can find that certain teams are repeating work unnecessarily or key tasks are falling by the wayside. By customizing competencies, you can also prevent further content management missteps. Using a competency based training program can further enhance this customization, ensuring each role receives training that’s precisely aligned with real job requirements. Misstep 4: Poor structural integrity “Whatever good things we build end up building us.” Jim Rohn When designing the structure of your competency management system you want to lead with a model of accessibility. You want the system to be usable. Consider everyone in the company, from the bottom to the top, and remember that not everyone will have the same intricate knowledge of the system. You don’t want your competency model growing into a massive overload of information that only one or two people in your company can sift through. While usability should always be first and foremost, businesses must also consider growth. Built into the smaller pilot model should be a model for growth as more departments, skills and competencies are added. Like any sound structure you want your competency profiles to build from level to level to avoid competency management missteps. Take care with the structure that you are setting as the foundation so that you are not building a house of cards. Misstep 5: Rushed results and follow-through fails “I can give you a six-word formula for success: Think things through – then follow through.” Eddie Rickenbacker As with any new system, there will be trials, errors, successes and modifications necessary. There will be competency management missteps, but there are ways to ensure your footing as well. Just as an organization is always growing and adapting, a management system will also need to continue to evolve. Throughout the process of implementation, it will be crucial to interview, and continue to ask questions and solicit feedback (even criticism) from employees and management. Starting small and slowly gaining momentum will involve testing, re-testing and constant data analysis. Finally, it is not always easy to see a competency management system implemented, even without the missteps. Ensuring that there is a devoted team to the project will help see the system through. Additionally, don’t let this team become isolated and so focused on their task that they miss out on the feedback from employees directly affected by the management system. Following through means listening to feedback and criticism, making modifications when necessary, starting small and building a solid structure. Are you having competency management missteps and need some questions answered? Reach out . Did you make missteps along the way that other people can learn from? Share your advice . FAQ What are common competency management missteps? The five most common missteps are trying to do too much too fast, overcomplicating competency language, failing to customize the system to your organization, poor structural design, and rushing results without proper follow-through. Why should you start small with competency management? Implementing everything at once overwhelms HR and management teams and increases the risk of failure. Starting with a small, focused pilot project lets you learn what works, refine your approach, and build momentum before scaling to the full organization. How does competency complexity become a problem? Too many levels, too many competencies, run-on descriptions, and redundant entries all overcomplicate the system. This confuses employees and managers, reduces adoption, and undermines the value of competency management. Simplicity and specificity are essential. Why must a competency system be customized to your company? Competency management is not one-size-fits-all. Generic frameworks miss the specific skills and behaviors that matter to your organization. Customized competencies can reveal inefficiencies, eliminate redundant work, and drive meaningful growth aligned with your business goals. What does poor structural integrity look like in competency management? A poorly structured system is one that only a few people can navigate, lacks scalability, and overwhelms users with disorganized information. Effective systems prioritize accessibility, build from level to level logically, and accommodate future growth from the start. How do rushed results undermine competency management? Expecting immediate outcomes skips the essential cycle of testing, gathering feedback, and refining the system. Successful competency management requires patience, continuous data analysis, and willingness to modify the approach based on real-world employee and manager input. How should competency definitions be written to avoid confusion? Use simple, specific language and avoid jargon-filled or unclear descriptions. Eliminate synonymous competencies and ensure each definition is distinct and measurable. Clear language drives consistent understanding across all levels of the organization. Why is employee feedback important during competency rollout? Employees are directly affected by the competency management system and provide critical insight into what works and what does not. Soliciting feedback, including criticism, helps you make necessary modifications and ensures the system serves its intended purpose. What role does a pilot project play in competency management? A pilot project serves as a controlled test of your competency management approach. It should be small, well-defined, and completable in a short timeframe. The results become a model for future rollouts and help you avoid scaling mistakes across the organization. How can a competency management platform help avoid missteps? A scalable competency management platform helps you implement gradually, maintain consistent structure across departments, and adapt as your organization grows. It provides the foundation for organized, accessible competency data that avoids the chaos of manual or ad-hoc approaches. --- ## How Talent Management Software Can Benefit SMB URL: https://skillsdb.com/blog/talent-management-software-smb Times are good in the U.S. economy and in the workforce. It’s hard to imagine there could be any downsides to this boom, but for many small and medium-sized businesses competing with large enterprises and corporations, attracting, retaining and investing in talent becomes a big challenge. The solution for small and medium-sized businesses to keep their competitive edge lies in talent management software. Talent management software is a tool to manage talent that automates, consolidates and streamlines talent management. It is a vital component to any sized business. Talent management software focuses on employee recruiting, development, performance management, compensation and succession planning. All of which are crucial in keeping businesses thriving and holding on to their most vital resource: employees. We’ve added nearly three million jobs in the last couple years and we have the lowest unemployment rate in 18 years. This is all fantastic news, right? In many respects, yes, but as more and more people find jobs, the market becomes talent-driven and large businesses with the capital often siphon off the best talent. As that talent pool evaporates, small and medium-sized businesses (SMB) are facing a crisis in talent management. Talent management software can sometimes make the difference in whether SMBs sink or swim in this new market. According to the State of Small Business Report , 50% of SMB owners report that hiring new employees was one of their top challenges. Hiring is a tough, time consuming and expensive process. Employee turnover is high, 32% total separations was the national average in 2017, according to Mercer. This is a big cost for businesses already struggling with human capital management. It is often a monumental task for HR departments and managers to effectively manage constantly evolving industries, technologies and work culture shifts, while also interviewing and managing new hires. HR departments stay small as companies grow and it is often improbable, if not impossible, to effectively manage talent with the systems used in the past. With the latest technology of talent management software, SMBs can transition talent management from a hectic, pain-filled process into a thriving environment for employees, management and owners alike. One of SMBs greatest assets is their familial workplace culture. Many employees choose to work for smaller businesses as opposed to corporations because they value relationships and employee-centered work culture. In the current economy, with competition for talent so aggressive, management is often stretched so thin with attracting and retaining their talent that they are unable to find time for those on-on-one interactions and meaningful connections that originally brought employees to SMBs in the first place. The end result, more employee turnover. In order to continue to retain and manage employees, identify areas for new trainings and employee development, HR departments and managers are finding increased resilience and new opportunities for managing human capital with talent management software. Many systems today also serve as a training platform for employees, helping teams keep pace with industry changes. Growth is often a primary drive for SMBs. While some may be focusing on revenue growth, others may be geared toward expansion in the industry or reaching consumers on a larger level. No matter the reason or mechanism behind the growth, any sized business can benefit from talent management software. In the growth stage from small to medium-sized, or medium-sized to large, businesses want to keep their personable nature. The key to maintaining employee-manager relationships and letting HR departments most effectively do their job, of course, lies in technology. This includes launching a skills development program to strengthen employee capabilities across departments. Any company’s greatest asset is its human asset. People matter, their satisfaction in the workplace matters. Happy employees often signal to the overall health of the company. It may seem counterintuitive for a software to be able to foster the happiness and health of workplace culture, but the overwhelming majority of businesses who employ some form of talent management inevitably experience greater employee retention, and recognized the strategic value of talent management systems and software. With the use of talent management software, SMBs create the framework to be able to: accurately identify employee skills, place employees on projects or in areas where their strengths can be put to best use, target key trainings that will increase productivity, identify areas for employee development, increase productivity and save time and resources for the company. Identifying the best investments for SMBs is essential for the vitality of so many organizations. Talent management software is one of the best ways to invest in the human asset of any company. Investment in technology, vs investment in the debilitating hiring process yields a far greater ROI. Talent management software is often the long term solution that business have been seeking for their employees. Contact us today for a free estimate and demo of the talent management software that will take your small or medium-sized business to the next level. FAQ What is talent management software? Talent management software automates, consolidates, and streamlines the processes of recruiting, developing, managing performance, and planning succession. It provides a centralized system for managing your most important asset: your people. Why do small and medium businesses need talent management software? SMBs face intense competition for talent from larger enterprises with deeper pockets. Talent management software levels the playing field by helping SMBs identify skills, target training, reduce turnover, and maximize the productivity of leaner teams. How does talent management software reduce employee turnover? It enables HR teams and managers to invest in employee development, identify growth opportunities, and maintain the personal connections that attract people to smaller companies. Employees who see a clear development path are far less likely to leave. What challenges do SMBs face in hiring and retention? Fifty percent of SMB owners report hiring as a top challenge. In a talent-driven market, large companies siphon off top candidates, HR departments stay small as companies grow, and the traditional tools for managing people cannot keep up with evolving demands. How does talent management software help growing companies scale? As businesses move from small to medium or medium to large, talent management software preserves the personable culture while systematizing skills identification, training, and development. It lets HR departments do more with the same headcount. What can a company accomplish with talent management software? Organizations can accurately identify employee skills, place people where their strengths are best used, target key training to increase productivity, identify development areas, and save significant time and resources that would otherwise go to manual processes. Is talent management software a better investment than more hiring? In most cases, yes. Investing in technology to develop and retain existing talent yields a far greater ROI than repeatedly paying the high costs of recruitment, onboarding, and the productivity loss that comes with constant employee turnover. How does talent management software preserve SMB workplace culture? By automating administrative talent management tasks, the software frees managers to focus on the one-on-one interactions and meaningful connections that employees value about working for smaller companies. It protects culture while enabling growth. What HR processes does talent management software automate? It automates employee recruiting workflows, skills identification, development planning, performance management, compensation tracking, and succession planning. This consolidation eliminates manual processes and gives HR teams a unified view of their workforce. How does SkillsDB serve as talent management software for SMBs? SkillsDB provides a skills intelligence platform that helps SMBs track employee skills, identify gaps, manage development plans, and make data-driven decisions about their workforce. It is designed to scale with growing organizations while remaining accessible and easy to use. --- ## How to Define Employee Skills for Your Organization URL: https://skillsdb.com/blog/how-to-define-employee-skills How many employees does it take to change a lightbulb? Don’t worry, there’s no bad punch line coming because the answer should be simple: one. The employee with the most qualified light bulb changing skills should be the go-to. Management should know who their light bulb changer is. The light bulb changer knows their position because, they got hired for this crucial job. In the case of light bulb changing, our hypothetical organization clearly knows how to define employee skills. In a perfect world, in a perfect company, employee skills perfectly match the duties and job responsibilities of each and every employee. But we all know this is not always the case and organizations do themselves and their employees a great disservice by not clearly defining employee skills. Not only could organizations maximize their investments on employees, but employees could better perform their jobs and more effectively take on projects. Using an employee skills platform can simplify this process, ensuring consistency and accuracy in skill tracking. There’s nothing new about any of these concepts or models. The skills match the job that needs to be done. But our workplace, our industries and our technologies are becoming increasingly complex and convoluted. Distilling the employee skills necessary for the job or project and the worker(s) that matches perfectly all these talents is a science unto itself. Managers in particular are having greater difficulty in putting together teams for projects and identifying and defining employee skills. To better understand how to define employee skills, let’s look to a real-world example Meet Elaine, she’s an IT manager for a long-standing company that is in a new growth phase. She’s been with the company for three months and she was brought on because she has a proven track record of bringing businesses with out of date systems into the modern era. Her first major project: migrating their entire old database, mostly spreadsheets, into a new Database Management System. Elaine can do this, but she’s so new, and the company’s IT department is so large, their skills so undefined, that she’s having a hard time choosing the right people for the job. Next, Elaine has gotten to know a few of the personalities. Jeff has a pug and wears a different color of socks each day of the week. Jasmine likes tacos and hates the smell of mint toothpaste. But their specific skills are less clear. Everyone in the whole department has learned their niche in the company and performs their jobs with diligence, but few can describe to Elaine what it is they really do, let alone define their particular skills. Furthermore, Elaine wisely, has realized the IT department’s shortcoming: how can she choose the right people for this project if she doesn’t know their abilities? And in the grand scheme of things, she needs to define these skills, the level of competency, the latest trainings, the gaps in education and certifications for each employee so that she can correctly place them in future projects. Elaine—the strong, fearless visionary that she is—realizes her company needs employee skills and competency management. Conducting an employee skills survey is her first step in uncovering these insights. With a comprehensive and systematized skills management structure in place, Elaine can create her dream team for any given project. Not only that, but she has benefitted her employees and employer in a number of invaluable ways. Pairing this with learning and development platforms can further enhance the team's capabilities and keep skills sharp and up-to-date. Steps to define employee skills For the employees, defining and managing skills helps: Identify current strengths and areas of expertise Identify deficits and skill gaps Target individual and group trainings needed to increase key competencies Place people where they are most knowledgeable and comfortable Recognize employee development opportunities (a key factor in increasing industry relevance and employee morale ) For the company, employee skills management facilitates: Increased productivity by putting the best people in positions that speak to their strengths Saved time and resources by streamlining the skills identification process for all projects A way to restructure teams to be more productive and effective Potential employee retention by identifying professional development trainings Elaine’s company, if they listened to her prudent suggestion and found a system to clearly define and manage employee skills, will now have alleviated and expedited a great many issues managers and employees come across every day. Your company, too, can benefit in key areas of performance , better achieving company objectives, identifying strengths and skills gaps, putting the right person in the right place and, most importantly, saving time and resources. Don’t take shots in the dark when it comes to crucial projects and investments in your business. In cases of critical management decisions, your money and energy are best invested in a comprehensive employee skills management system. Contact us for a free demo on SkillsDB—an advanced employee skills platform designed to transform your workforce strategy. FAQ Why is defining employee skills important for organizations? Clearly defined employee skills enable organizations to maximize their investment in people, place the right person on the right project, and identify training gaps. Without defined skills, managers struggle to build effective teams and employees cannot articulate their own capabilities. What are the steps to define employee skills? Start by identifying current strengths and areas of expertise, then uncover deficits and skill gaps. Target individual and group training needs, place people where they are most knowledgeable, and recognize development opportunities that increase both relevance and morale. How does defining skills benefit employees directly? Employees gain clarity on their strengths, understand where they need to grow, and receive targeted training aligned with their actual gaps. It also places them in roles that match their expertise, which increases job satisfaction and career development opportunities. How does skills definition benefit the company? Companies experience increased productivity by putting the best people in the right positions, save time and resources through streamlined project staffing, and improve retention by investing in meaningful professional development. It eliminates guesswork from critical management decisions. What challenges do managers face without defined employee skills? Managers struggle to assemble the right teams for projects, cannot identify which employees have which capabilities, and make staffing decisions based on personality or proximity rather than competence. This leads to missed deadlines, project failures, and wasted resources. What is an employee skills survey? An employee skills survey is a structured assessment that captures each employee's self-reported skills, competency levels, training history, and certification status. It provides the baseline data needed to build a comprehensive skills management system for staffing and development decisions. How does skills management help with project staffing? With a systematized skills management structure, managers can quickly search for employees with the exact competencies a project requires. This eliminates the guesswork of team assembly and ensures projects start with the right capabilities in place. Why is skills definition harder in modern workplaces? Industries, technologies, and work cultures are becoming increasingly complex. Distilling the exact skills needed for a job and matching them to the right employees requires a systematic approach that goes beyond informal knowledge or tribal memory. What happens when organizations skip employee skills definition? Organizations make uninformed decisions about project staffing, miss opportunities for employee development, and waste resources on mismatched training. Employees end up in roles that do not leverage their strengths, leading to lower productivity and higher turnover. How does SkillsDB help organizations define employee skills? SkillsDB is a skills intelligence platform that helps organizations systematically define, track, and manage employee skills across the workforce. It provides tools for skills surveys, competency assessments, gap analysis, and data-driven project staffing decisions. --- ## How to Create Employee Development Plans that Really Work URL: https://skillsdb.com/blog/create-employee-development-plans I was chatting with a client last week, they are spending lots of money on training and not really sure about the actual effectiveness of their spend. This conversation ended up with us spending a lot of time dissecting how to create employee development plans that really works. The Association for Talent Development (ATD) suggests that organizations are investing more money into employee training than ever before. In their most recent State of the Industry Report they found that companies spend an average of $1,273 per employee on direct learning courses and employee development plans. It’s easy to see why this rise in learning expenditure is the case though. According to research by PwC, the rise in learning and development costs has been spurred on by the expectations of millennials in the workplace . Apparently 35% of millennials claim that they’ll prefer an employer who offers training and employee development programs. Deloitte agree with PwC, suggesting that if an organization doesn’t offer professional development opportunities they’ll have a hard time retaining their younger talent . Millenials are the most highly educated generation to date, and they’ve grown up accustomed to operating in a fast-moving world. Oh, and don’t forget that everyday they’re exposed to a workplace with lower job security than ever. Learning is crucial, not just for employees, but the organizations who employee those people. So that begs the question; how can you create employee development plans that actually work? One effective approach is to use an employee skills platform that helps identify strengths and gaps through an employee skills survey, providing a clear baseline for targeted development. Creating employee development plans that work well We’ve decided to highlight five things your company can do to create effective employee development plans. To ensure that they’re as effective at helping your employees learn as you need them to be. 1. Encourage senior employees to get involved (their knowledge is priceless) Your junior employees can learn from nobody better than someone who’s been there and done their role in the past. Incentivising managers to lead employee development programs and share their knowledge is not only beneficial for the trainee but also for the manager as it’s a prime opportunity for them to further their leadership and management skills. 2. Enable junior employees to take ownership over their own plans While it’s a good idea to put a structure in place for employee development plans. Furthermore, it can be wise to allow younger employees the capacity to shape their own development plans based on their interests and career aspirations. For example, if someone on your marketing team wants to learn more about coding, your initial reaction might be to suggest they focus on marketing-related courses. However, if the marketer has interest in learning code so that they can become a UX designer in the future that might be of interest to the organization in the long term as well. Using a learning and development platform that supports personalized paths can empower employees to drive their own growth while aligning with company goals. 3. Provide flexible working options Asking employees to do intense professional development on top of their already busy schedule might not be the wisest of ideas, particularly if you require the employee to be situated on-site or have to do their training with other. By offering on-demand and mobile courses, companies can make development plans more accessible and enjoyable. That point stands true for remote-based workers too, or even people who prefer to learn entirely outside of the office. To learn more about setting up your employees remotely check out this blog: Solving The 6 Major Challenges Of Managing Remote Teams 4. Align different learning options with different learning styles The way the that Baby Boomers learned their trade is quite different from the way that some Millennials approached it. Couple that with the fact that some people prefer to learn by reading while other choose to listen, or taken in more through visual learning, and you have a small conundrum! Creating employee development plans which offer people the chance to choose which learning style they prefer is a great way to not only increase the effectiveness of the plan, but also make the entire process more enjoyable and rewarding for the participants. Implementing a skills development program that offers diverse formats caters to varied preferences and maximizes engagement. 5. Track the progress of your trainees Use employee training tracking software to measure and monitor the employee development plans from start to end. Why? Well, you can manage and track how each employee is progressing through their plan, e.g., are they on schedule? Are they struggling on certain sections? What’s more, you can use the software to link documents and information to particular employees, as well as generating reports on performance. An effective upskilling program for employees includes regular assessments and feedback loops, which can be managed easily through the right platform. How to apply this to your business Any software you choose to manage employee development plans should be easy and quick for your employee to engage with. I hope that by sharing our own experiences cracking the code for effective employee development plans that make the team and skills stronger, this post helps you have better trainings, become more productive and develop a better culture as a result. FAQ What is an employee development plan? An employee development plan is a structured program that identifies skills gaps, sets learning objectives, and provides targeted training to help employees grow professionally. Effective plans align individual career aspirations with organizational business goals. How much do companies spend on employee development? According to the Association for Talent Development , companies spend an average of $1,273 per employee on direct learning courses and development plans. This investment continues to rise as organizations recognize the link between development and retention. Why do millennials expect employer-provided development programs? Research from PwC shows that 35% of millennials prefer employers who offer training and development programs. As the most educated generation to date, they expect continuous growth opportunities and will leave organizations that do not invest in their professional development. How should senior employees contribute to development plans? Senior employees bring invaluable on-the-job knowledge that cannot be replicated in a course. Incentivizing them to lead development programs benefits trainees through real-world expertise while strengthening the senior employee's own leadership and management skills. Should employees have ownership over their development plans? Yes. Allowing employees to shape their development plans based on personal interests and career aspirations increases engagement and uncovers growth paths that benefit both the individual and the organization in the long term. Why do flexible working options matter for employee development? Asking employees to do intensive professional development on top of a full schedule leads to burnout and disengagement. Offering on-demand, mobile, and remote-friendly learning options makes development plans more accessible and more likely to be completed. How should development plans accommodate different learning styles? People learn differently through reading, listening, watching, or hands-on practice. Offering multiple learning formats within development plans increases effectiveness, improves completion rates, and makes the entire experience more rewarding for participants. Why is tracking progress essential in employee development? Tracking progress lets managers monitor whether employees are on schedule, identify where they are struggling, and intervene with support before problems compound. It also generates performance reports that demonstrate the ROI of development investments. What makes an employee development plan effective? An effective plan combines senior mentorship, employee ownership, flexible learning options, varied formats for different learning styles, and consistent progress tracking. The software used to manage it should be easy and quick for employees to engage with. How do skills surveys support employee development planning? Skills surveys establish a clear baseline of each employee's current strengths and gaps. This data ensures development plans target actual deficiencies rather than assumed ones, making every training investment more precise and impactful. What role does employee training tracking software play? Training tracking software measures and monitors development plans from start to finish, links documents and resources to individual employees, and generates performance reports. It provides the visibility needed to manage development programs at scale. --- ## 3 Steps to Successfully Implement Employee Training Software URL: https://skillsdb.com/blog/employee-training-tracking-software Every month during client calls, we get dozens of questions about best practices for creating a successful training program. Employee Training Tracking Software implementations make up a large part of this number. In this article I will give you some tips for implementing a training tracking system with the best possible outcome. In 2017, there was a reported 32.5 percent increase to $90.6 billion on training expenditure by US-based organizations. Employee Training Tracking Software implementations make up a large part of this number. It’s a figure that is being driven higher every year by several factors, but two of the most important are: A desire from millenials for more learning opportunities: 59 percent of millennials say opportunities to learn and grow are extremely important when they’re applying for new jobs Employee retention rates increase: Research shows that new employees who experience a well-structured onboarding program are 69 percent more likely to remain at that company for at least three years . Considering millennials are going to comprise the bulk of the workforce by 2030, and that the cost of employee turnover is ever-increasing, it’s important that your business has a thorough employee training program in place. This is where choosing the right employee training platform can make all the difference in delivering effective learning experiences. Let’s takes a look at the steps involved in building out a successful training program and implementing tracking software to measure its performance. Building an effective employee training program Identify what training your employees need Before you even begin design your training program you should figure out exactly what training your employees needs in order to have the most impact upon your business. Starting with a skills gap analysis will help you identify areas where the business may be currently lacking. It’s also helpful to ask your employees what they would like to learn about. While you might have a high-level overview and understanding of your business, your employees can offer a fresh perspective and help you determine which skills or traits could be useful for current, and future, employees to have. Asking questions such as the following might be a great place to start: What do you think you struggle with the most at work? What way do you learn best? How could we help your team improve its performance? Are there any interests you have outside of work that you’d like to learn more about? Once the needs and desired skills have been identified it’s time to begin planning your employee training program and set your program objectives. Many organizations now focus on upskilling programs for employees to ensure their workforce stays competitive and capable in evolving roles. If you want to learn more about how to define skill gaps, read this post . Setting objectives based on your business and employee needs It’s crucial to define the goals and objectives of your training program before you actually take any strides. Training new employees without any real direction will inevitably result in unimpressive outcomes. You can use a series of criteria or parameters to formulate your questions, such as: How will team performance improve after the completion of the program? Example: “The customer success team will be able to respond to questions X% faster using (x) tool” Why will employees be in a better position to hit their targets after the program? Example: “The sales teams will be able to use (x) platform to target our ideal customers” How will the training prepare employees for future leadership roles? Example: “X employee will be able to implement constructive performance reviews for his/her team” How will this program improve employee retention rates? Example: “Our turnover rate next year will decrease by X% after we plan team-building activities that boost employee morale and retention ” Now that you’ve determined what you need from your training and what your objectives are, it’s time to put in place the process of measuring your training’s performance. Using employee training tracking software to measure the success of your program In the same way that you assess your employees and their team performance, you should put in place the appropriate measures to track the performance of your employee training programs. You can use two methods to help paint a picture of how successful your training program has been: Conduct employee interviews and use feedback to help you inform the process in the future. This might include questions such as: What new (e.g. task, tool, skill) did you learn from the program? How will (or did) you apply this newly-acquired knowledge on the job? What did you like about the program and what should we improve (e.g. topic, methodology, instructor, material)? Use employee training tracking software to measure and monitor the training process from start to end. The benefits of using employee training tracking software include: The ability to manage and track employee training events through the use of employee profiles and requirements Set up links to documents and control which employees see certain records Generate reports on training performance including updates on submissions and progress By leveraging employee tracking software alongside direct feedback, companies can identify which of the best training programs for employees are driving real results. Over time you’ll be able to use both of these methods in tandem to help you gauge the effectiveness of your training programs. FAQ What is employee training tracking software? Employee training tracking software is a platform that lets you manage, monitor, and measure employee training programs from start to finish. It provides tools for tracking training events, managing employee profiles, linking documents, and generating performance reports. How do I identify what training employees need? Start with a skills gap analysis to pinpoint areas where your workforce is currently lacking. Supplement that by surveying employees directly about their struggles, learning preferences, and interests to get a ground-level perspective on training priorities. Why should I set objectives before launching training? Training without clear objectives leads to unfocused programs and unimpressive outcomes. Defined goals let you measure impact on team performance, employee retention, and leadership readiness so you know whether your investment is actually paying off. How does training tracking software measure program success? It tracks training events through employee profiles and requirements, generates reports on submissions and progress, and links relevant documents to training records. Combined with direct employee feedback, it gives you a complete picture of what is working and what needs to change. What are the benefits of using training tracking software? Key benefits include centralized management of training events, the ability to control document access per employee, and automated reporting on training progress. These capabilities replace manual tracking and give you data-driven insight into program effectiveness. How does employee training impact retention rates? Research shows that new employees who experience a well-structured onboarding program are 69 percent more likely to stay for at least three years. Investing in training signals to employees that the company values their growth, which directly reduces turnover. Why are millennials driving training investment increases? Fifty-nine percent of millennials say learning and growth opportunities are extremely important when evaluating jobs. With millennials set to comprise the bulk of the workforce by 2030, companies that fail to invest in training will struggle to attract and retain this talent. What is a skills gap analysis for training? A skills gap analysis identifies the difference between the skills your workforce currently has and the skills your business needs. It serves as the foundation for designing targeted training programs that address real organizational weaknesses rather than guessing at what employees need. How do upskilling programs fit into training tracking? Upskilling programs are structured initiatives to build new capabilities in your existing workforce. Training tracking software lets you monitor participation, measure progress, and report on outcomes so you can prove ROI and continuously refine your upskilling strategy. What questions should I ask employees after training? Ask what new skills or tools they learned, how they plan to apply that knowledge on the job, and what they would improve about the program. This feedback loop helps you iterate on content, methodology, and delivery for future training cycles. --- ## Needs Analysis Dashboards for Administrators URL: https://skillsdb.com/blog/needs-analysis-dashboards-for-administrators For some time, we deliberated on creating an informational dashboard for our users. And, we recently went ahead and implemented not just one, but two dashboards. The first is the main dashboard which keeps you updated on your people’s skills and activity in the system. The two sections on the top left let you know how your people are using the system. On the first stat, you can see the number of people who are yet to add skills to their profile. The second stat shows you how many skills are updated each month. In particular, with this data, you can decide if your people are active enough, or if you need to send out a notification reminding them to use the system. It may also help you keep track of employee development initiatives. If skills are not being developed, employees will have few or no skills to update, and this stat will drop. The “Top Skill Averages” section at the bottom helps you identify the skills for which your people are most competent. It brings this information out by displaying skills that at least 5 people have. For those, the average score is at least 3 (Competent). The “Training Needs Analysis” stat on the right gives you a sneak preview of the skills for which your people need training. Further, we designed a dedicated Training Needs Analysis dashboard with which you can get more insight. Training Needs Analysis Dashboard We thought about it carefully and decided all the functionality needed for in-depth Training Needs Analysis could not be fitted into the Main Dashboard. Thus, we chose to create a separate Training Needs Analysis dashboard. With this dashboard, you can create custom TNAs, unique to your requirements, and the needs of your company. One simple way to find out your company’s training needs is to pull out skills that meet the following two criteria: 1. Quite a few employees have the skill. 2. The skill has a low skill score rating across employees. If there is a particular skill that quite a few people own, this may indicate that the skill is important to the company. If you, then, find out the average score for this skill is less than “Competent”, it may be time to train. With our new TNA dashboard, you can find this out very easily. With the first section on top, you can ask the system to return skills that are owned by at least X number of people, for which the average score is less than Y. After specifying the values and hitting Refresh, the TNA graph refreshes to show you the results of your query. And, from this graph, you can pick out skills for which your people need training (See TNA graph above for a sample). The Report But it doesn’t stop there. Below the TNA graph, there is a simple report. If you drag the “Person” filter in front of “Skill” as shown in the picture below, the report shows you each individual who has the skill, and what their score is. With this information, you can select people to be trained. And, people who are competent enough to handle the training. As you can also see in the picture, there are many other ways you can drill down on this data. If your company is spread out across multiple cities, you can add the city filter, etc. We hope by now some of you have taken our dashboards for a spin and have found out how they can give you insights into the activities and needs of your workforce. If you are yet to do this, this article has shown you ways in which this new feature can help you keep your workforce in top shape. Please take advantage of it and continue to reap the benefits of using Skills\DB to manage your workforce. FAQ What is a Training Needs Analysis dashboard? A Training Needs Analysis (TNA) dashboard is a visual tool that helps administrators identify skills gaps across their workforce. It surfaces skills where many employees score below competency thresholds, so you can prioritize training investments where they matter most. How does the main administrator dashboard work? The main dashboard shows two key metrics: how many employees have yet to add skills to their profile, and how many skills are updated each month. It also displays top skill averages and a preview of training needs, giving you a quick pulse on workforce engagement and competency. How do I identify which skills need training? Use the TNA dashboard to filter skills owned by at least X number of employees where the average score falls below Y. Skills that are widely held but poorly rated signal a critical training need because they are important to the business but underdeveloped across the team. What does the TNA report show administrators? The TNA report breaks down each skill by individual employee and their score. You can drag the Person filter in front of Skill to see exactly who needs training and who is competent enough to deliver it, enabling precise training assignments. Can I filter TNA data by location or department? Yes. The TNA dashboard supports multiple filters including city, department, and other organizational attributes. This lets you drill down into specific segments of your workforce to identify location-specific or team-specific training gaps. What does Top Skill Averages tell me? Top Skill Averages highlights skills where your organization is strongest. It displays skills held by at least five employees with an average score of Competent or higher, helping you understand your workforce's core strengths at a glance. How do dashboards help track employee development? By monitoring monthly skill update activity, you can see whether employees are actively developing their skills. A drop in updates may signal stalled development initiatives, prompting you to send reminders or adjust your engagement strategy. Why use a dedicated TNA dashboard instead of reports? A dedicated TNA dashboard provides interactive, real-time analysis that static reports cannot match. You can adjust thresholds, apply filters, and visually explore the data to make faster, more informed decisions about training priorities. --- ## 4 Things You Didn't Know About Creating a Skills Management System URL: https://skillsdb.com/blog/4-things-you-didnt-know-about-creating-a-skills-management-system About a year ago, SkillsDB was at a very important point in its history. At that time, we noticed we were losing clients because they wanted a feature we did not want to implement. The feature was permitting employees to define skills as they use their skills management system. At that point, we knew the mess this could lead to if not done properly, so whenever this feature came up, we held our heads high like soldiers in a Chinese military parade, and said no! After some time though, we noticed that Steve’s position on this began to shift. He was probably thinking what I was thinking – “If this is what they want, then it’s our obligation to give it to them.” So like a good pharmacy, we produced the feature to ease the pain of our clients, wrote the prescription, and clearly outlined the potential side effects. One week passed, then one month, then one year, and up till this day, we haven’t gotten a single complaint from our clients about this feature leading to an issue. On the contrary, thanks to this feature (and others), you can literally start using your skills management system in a few hours. And that is the first thing you didn’t know about creating a skills management system. 1. You don’t need weeks to implement your skills management system Implementing HR systems can be an unusually complex process. Many people come to us with the mindset that getting their skills management system up and running is going to be very hard, so even before they start, they’re defeated. Quite contrarily, modern skills management systems are designed to be “easy to use.” At SkillsDB, we live by those words, so we spent a lot of time, research, and effort to get you the features needed to make this as easy as possible. There are two basic steps in getting a skills management system ready for your people to use: Define Personnel Define Skills In SkillsDB, those steps are actually “import personnel” and “import skills.” To import your personnel , you can simply export their data into a spreadsheet (possibly from your payroll management or HR system), and then import them into SkillsDB. We provide clear instructions and are always ready to guide you to make this a smooth process. To import company skills , we provide you with a skills template in Excel format. You can simply share this with department managers and have them populate it with the skills in their department. After that, you import the template into our system and all your skills information are ready to use. When setting up skills, you may also decide instead to use the feature we spoke about at the outset. Using this feature, you will need to do zero skills setup work. Simply import your people and allow them create the skill they want to rate themselves on. If one employee creates a skill, others would be able to see and rate themselves on that skill. So in a short time, you would have a complete skills list. Reach out if you want to cut out the hassle and get your system up and running before the clock strikes “Midweek.” 2. Implementing skills management can save your company much money (according to company reports) If you were looking for a way to sell top management on your need to implement a skills management system, please put down your phone, drop those papers, tell Mr. John to keep silent for a moment, and listen – “Skills Management Can Save Your Company Much Money.” But How? For one thing, you can hardly fully utilize your people if you have no way of tracking their skills. So the first source of financial gain comes from better utilization of personnel, and this is far more important than it may seem at first. Case in point: “Speaking about a client he worked with, Andy Andrews of Salary.com said ‘they were spending too much money on contractors and external resources. They had in-house skills but they did not know where they were in the organization. It was easier for them even if more expensive to go out and hire external resources.’” “[This Company] was able to reduce this spending by implementing skills management. With the system in place, they knew the skills that were available in the company, and the people who had those skills. They could thus utilize their people and reduce external contracts.” Additionally, a well-structured skills development program integrated with a robust skills management platform can enhance employee capabilities and reduce costly external hires. To learn other financial and organizational benefits of skills management, please read “ The Impact of Skills Management on Business Performance. ” 3. Training and Succession planning without skills management is like shooting in the dark A company I work with decided to expand a while back. Our CEO sought executives from various fields, even hiring a past executive of one of the biggest fast-food franchises. In all, four people were hired. Less than a year later, not one of the executives remained. They all washed out because the company culture was new to them, and they could hardly cope. After this happened, our CEO finally realized what she should have done all along. She started promoting from within, and our diligent operations manager quickly became a director. Ideally, most top positions should be filled via promotion. But when it comes to the issue of succession planning, many companies still do not know what they are doing. The first step in succession planning is identifying talent. A skills management system helps ensure you properly identify talents and groom them right from the beginning. Since succession takes a lot of training and mentorship, it would be counterproductive to spend all that on a less than ideal candidate. With a skills management system in place, you’d be able to identify employees who have core skills which are useful for the job, and soft skills which are needed for leadership, right from early on in an employee’s career. The system will also help management strengthen and reassess these skills over time. Without this data, if top management only relies on recommendations from people, they’re shooting in the dark. A comprehensive employee skills platform can make your Skills Development Program more strategic and effective for succession planning. 4. Implementing a skills management system is surprisingly pocket friendly A decent breakfast for 2 = $25 SkillsDB Starter Plan = $100/Month For a system that can save your company money and increase talent utilization and company productivity, you might expect it would cost more right? Well it doesn’t. How Can You Use This Information? If you were planning to implement a skills management system for your company, you might have had some misconceptions about the difficulty, cost, and benefits of getting this done (many people do). I hope this post has cleared up some of those. The points made in the post are based on what is obtainable with our software, so if you would like to quicken your implementation process, please give us a call (720 457-3312), or book a live demo . We would be happy to get you up and running if our system matches your use cases. If not, you can rest assured we would point you in the right direction. FAQ How long does it take to implement skills management? Modern skills management systems like SkillsDB can be up and running in hours, not weeks. The two core steps are importing your personnel and importing your skills, both of which can be done via spreadsheet uploads with guided support. What are the two steps to set up skills management? The two fundamental steps are defining your personnel and defining your skills. In practice, you export employee data from your existing HR or payroll system and import it, then populate a skills template with department managers and import that as well. Can employees define their own skills in the system? Yes. Rather than requiring admins to predefine every skill, you can allow employees to create skills as they rate themselves. When one employee creates a skill, others can see and rate themselves on it too, organically building a complete skills inventory with zero setup work. How does skills management save companies money? Skills management improves financial outcomes by enabling better utilization of existing personnel. Companies often overspend on contractors and external hires simply because they do not know what skills already exist in-house. A skills inventory eliminates that blind spot. Why is skills management critical for succession planning? Without skills data, succession planning is guesswork. A skills management system helps you identify employees with the right combination of core competencies and leadership soft skills early in their careers, so you can develop them intentionally rather than scrambling when a role opens up. What happens when companies promote externally instead of within? External hires for senior roles frequently fail because they lack familiarity with company culture and processes. Skills management helps you identify and groom internal candidates who already understand the business, reducing failed placements and the associated costs. How much does a skills management system cost? Skills management systems are surprisingly affordable. SkillsDB plans start at price points comparable to everyday expenses, making it accessible for organizations of all sizes given the significant returns in talent utilization and workforce productivity. What misconceptions do people have about skills management implementation? The three most common misconceptions are that implementation is complex and time-consuming, that costs are prohibitively high, and that the benefits are vague. In reality, modern platforms are designed for rapid setup, affordable pricing, and measurable impact on utilization, training, and succession planning. How does skills management improve training effectiveness? Skills management provides data on where competency gaps exist across your workforce, so training investments target real weaknesses instead of assumptions. This data-driven approach ensures training budgets deliver maximum ROI by focusing on business-critical skills. Can I import existing employee data into SkillsDB? Yes. You can export employee data from your payroll or HR system into a spreadsheet and import it directly into SkillsDB. The platform provides clear instructions and guided support to make the migration process fast and smooth. --- ## 6 Outdated Interview Practices That Make You A Horrible Recruiter URL: https://skillsdb.com/blog/6-outdated-interview-practices-that-make-you-a-horrible-recruiter There was a time when floppy disks were the rage. You could throw a few floppies in your bag and get access to 5 megabytes of storage. And, that was great, even high-tech at the time. But if you hold a floppy in public today, don’t be surprised if passersby scan the area for the cave you emerged from. Yes everything changes eventually, and those who succeed are those who can keep up with change. Yet in many areas of recruitment, we find people who are holding on to outdated interview practices that should have seen their last days years ago. Many highly talented people lament about the lack-luster interview experiences they’ve had, and from the evidence available, it’s clear that many recruiters are harming their ability to recruit top talent by sticking to interview processes from the 18th century. And so in our post for this month, I would be shining the light on 6 outdated interview practices that should be scrapped right away, by every recruiter on the planet. 1. Using a precise, rigid set of questions, every time Interview a surgeon, same questions. Interview a programmer, same questions. Everybody has to fit into a specific mold of what is considered an ideal employee. There are probably a thousand problems with this approach, but let me bring out two. First, you end up hiring people with a set of criteria that ensures they are all alike. This can harm a company because diversity in personality and talent is great for creativity. The second and most obvious problem is that such cookie cutter criteria are not adequate to determine if individuals are suitable for the particular roles for which they are being considered. A much better approach is to use skills assessment tools as part of your recruitment process. These tools allow you to evaluate a candidate’s actual abilities and match them accurately to the job requirements, rather than relying on generic questions. 2. Interviewing people you do not plan on hiring I read a post recently from a candidate who apparently had a great interview with a company for a clearly advertised position, but who (after discussing a start date with the company) got a call from HR and was informed the position never existed. Here’s how the candidate felt: “I am so angry and confused. I spent a ridiculous amount of time on this job. Also, I updated my resume, wrote a cover letter, filled out an extensive online application. Then I did an hour-long exam to show I was qualified. Then I did a phone interview, using my vacation time at work. And, then I completed a detailed online profile with the company and did a background check that required me to provide the dates and addresses for every job I’ve ever had and every place I’ve lived for the past 10 years (I even had to reach out to previous landlords and roommates to make sure it was accurate). And for the interview itself, I spent countless hours preparing for different questions. All for a job that doesn’t exist.” Frankly, you can’t read that without feeling sorry for this candidate. A recruiter who is in the habit of performing interviews just to fulfill company policy, or for any similar reason, is quite frankly an unkind person. I can’t put it more pleasantly. There are however times when a company might perform a few interviews just to see what’s out there, and there’s nothing wrong with this as long as the candidates are duly informed about the purpose of the interview. 3. Letting HR do the entire interview Many companies no longer make this mistake. Nowadays you often have to sit with the manager of the department you are applying to, as well as a few team members before you are considered for the job. And this makes sense. Of course HR should coordinate the interview, and possibly perform the first interview. But when a candidate shows promise, it is time for them to be interviewed by those who know best, what is required for the role. And who better than the department manager, and other potential work mates. Modern talent management software can help coordinate this multi-level interview process smoothly, ensuring the right people are involved at the right stages without unnecessary delays. 4. Using a long, drawn out interview process. The suggestion above doesn’t mean the candidate has to be interviewed by the whole company. Some companies perform so many interviews per candidate that their process has appropriately been termed “Death by interview.” For example, the CEO of one technology firm required that each new candidate goes through “17” interview sessions. Now if I had seen this in a comedy column, it’ll be funny, and I’d laugh, and I’d move on. But to know that a company actually wants (or wanted) candidates to go through 17 interviews just makes me wonder, because this is inherently a waste of time and resources for the company, and torture for the candidates. In the past, Google also had the practice of subjecting candidates to double digit interviews. “Fortunately, its well-earned death-by-interview reputation forced Google to eventually conduct internal research that demonstrated that ‘after four interviews, you get diminishing returns.’” – Eremedia 5. Not following up with a candidate after an interview I wrote an article about poor recruitment practices last year ( read it here ) and this item also made that list. Maybe I’d start randomly including it in every article I write, just to get people to take note. The truth is, it is quite awful for a person to spend many hours preparing for an interview, go through the tough interview process, and then sit down and watch their phone and email until they decide to give up. When people who had this experience were polled, many decided that they would not become customers of the company involved if they needed the goods or services it offers. So aside from being unfair to the candidate, this practice can also make you lose customers. When candidates do not make the cut, find time to tell them they didn’t. If you are short for time, send out an email blast to them. A simple BCC to all candidates in this category may even do the job. And this should only take 10 minutes of your time. 6. Selecting people based on biased factors (university attended, race, etc.) The best candidates may not have attended an Ivy League University, so if you tend to give preference to these candidates, you are narrowing your talent pool, and harming your process. Also, while we want to believe racial bias is completely behind us, the truth is, it isn’t. A recent research concluded that African-Americans are 16% less likely to be called for interviews. There are many possible kinds of bias in recruitment, some may even be unique to a particular recruiter. However, a good recruiter should be able to get over any bias to ensure employees are selected based on how suitable they are for the role, and nothing else. How Can You Apply This Information This list of outdated interview practices is by no means exhaustive. It only brings out some of the major practices that make job applicants reconsider starting a business instead of working with your company. You can start from this list and weed out these practices from your process if any of them are still being used, and then go on to examine your whole recruitment process to see what else should go, and what should remain. The fact is, the modern business world evolves at the speed of light. And recruiters stand in the forefront of each company’s effort to keep up (and even lead) by bringing in the right talent. But if your recruitment process is outdated, you may end up being a drain on your company’s success. Nobody wants to be that. FAQ What are the most outdated interview practices today? The most damaging outdated practices include using rigid identical questions for every role, interviewing candidates you do not plan to hire, letting HR conduct the entire interview alone, subjecting candidates to excessive interview rounds, failing to follow up after interviews, and selecting based on biased factors like university or race. Why are rigid interview questions bad for recruiting? Using the same questions for every candidate regardless of role produces a homogeneous workforce and fails to evaluate whether someone is actually suited for the specific position. It kills diversity of thought and misses the skills that matter for the job at hand. How many interviews are too many for candidates? Google's internal research found that after four interviews, you get diminishing returns. Excessive interview rounds waste company resources, exhaust candidates, and often cause top talent to drop out of the process before you can make an offer. Why should department managers participate in interviews? Department managers and potential teammates understand the actual day-to-day requirements of a role far better than HR alone. Their involvement leads to more accurate assessments of technical fit, cultural fit, and the candidate's ability to contribute to the team immediately. What happens when recruiters do not follow up? Candidates who never hear back often refuse to become customers of that company and share their negative experience publicly. A simple rejection email takes minutes to send but protects your employer brand and shows basic respect for people's time and effort. How does interviewing bias harm the hiring process? Bias based on university, race, or other irrelevant factors artificially narrows your talent pool and leads to worse hiring outcomes. Research shows African-Americans are 16 percent less likely to be called for interviews, meaning biased recruiters systematically overlook qualified candidates. How can skills assessments improve the interview process? Skills assessment tools evaluate a candidate's actual abilities and match them to specific job requirements rather than relying on generic questions. This produces more objective, role-relevant hiring decisions and reduces the influence of unconscious bias in the process. Is it ethical to interview candidates for nonexistent roles? No. Interviewing candidates for positions that do not exist wastes their time, erodes trust, and damages your employer brand. If you are conducting exploratory interviews to assess the talent market, candidates deserve to be informed of that purpose upfront. How do outdated practices affect employer brand reputation? Poor interview experiences travel fast. Candidates who face ghosting, excessive rounds, or disrespectful processes share those stories publicly and with their networks. This directly shrinks your applicant pool and makes it harder to attract the talent your company needs. What is a modern approach to structured interviewing? A modern approach combines role-specific questions with skills assessment tools, limits the process to four or fewer rounds, involves the hiring manager and team members, and includes timely follow-up with every candidate. The goal is to evaluate actual job fit efficiently and respectfully. --- ## Solving the Major Challenges of Managing Remote Teams URL: https://skillsdb.com/blog/conquering-6-major-challenges-of-managing-remote-teams Few people could have imagined how much the internet would transform our activities. Probably not even Robert Kahn and Vincent Cerf, the guys who invented the internet. One area that has seen the most change is the way we work. It didn’t take long for people to realize that they didn’t need to meet in an office to discuss a client, or share a file. It could all be done through the internet. A few months after I got my bachelor’s degree, I started working. From that time till today, I’ve had the pleasure of working with a number of teams, But, I’ve never stepped in an office. I’m either at home or in a beautiful city mall with my laptop and internet dongle. And yes, remote work is just as great as people describe it. How do things work now? Nowadays, it’s not hard to see a company that has a team of 10 people, who are spread across every continent on the earth. Even companies that have all their workers living within a city (or country) now give the option for people to work from home. Yahoo is one such company. But, if you have been following the news, you may be aware that in 2013, the CEO tried to end remote work for all employees. Apparently, she wasn’t completely successful. And, frankly, it’ll have been quite a surprise if she was. Many other companies are heavily dependent on remote workers, and the stats favor this choice. A blog post in the Harvard Business Review website shows that remote workers are actually more productive that in-office workers. These stats make sense when you consider it takes a motivated self-starter to be able to work remotely in the first place. However, while there are clear advantages to telecommuting, it has also introduced a new set of challenges, many of which revolve around the very fabric of telecommuting: “the workers are not together in the same building.” This blog post highlights the challenges of managing remote teams, why they exist, and how to deal with them. The challenges, the solutions 1. Communication Effective communication is important in all settings. For a remote team however, it is “communicate effectively, or close up shop.” Getting people in different locations to achieve a common goal takes being able to master remote communication. Thankfully, the internet offers many powerful tools that can make this easy. The key is to take advantage of these tools in harmony with some best practices. For example, for a team to work effectively together, they need to communicate at least once each day. Even when tasks are specified, it makes sense to get the team together via Skype, Gotomeeting, or a similar tool. In these sessions, team members can update others on their progress, challenges encountered, skills learnt in the course of performing duties, etc. Here’s a power tip you should try; At the start of each workday (say by 9am) get team members together via a conference session. After discussing major issues, encourage team members to remain connected to the line for one more hour. If anyone has any question, or a suggestion for the team, they simply unmute, speak up, and continue communicating. 2. Getting the right people One of the most important steps in managing a remote team is choosing the right people in the first place. The truth is, not everyone can work effectively from a remote location. If a person needs much assistance to get the job done, chances are that person is more suitable for an in-office position. When looking for remote team members, find people who can demonstrate (or have demonstrated) their ability to manage time, handle tasks, and deliver results. These people should also be highly motivated. A good way to recruit suitable people is to hire on trial basis. Within the trial period, you can assess the person’s work. And, you can also determine if they are a good fit for your team. 3. Keeping track of activities “Oops, did you already message the customers in that list? I just sent them another email, my bad” A – “Hi B, are you through with the backend of the report builder, I just rounded up work on the front end and need your code to wrap it up for release tomorrow” B – “Hello A, I stopped working on the backend to finish work on our competency module. We may have to inform customers that the report builder will not be available till next week.” You get the point. Within an office, it is sometimes hard to keep track of activities. It is even more difficult in a remote setting. For a remote team to function together, each team member needs to know exactly what other team members are working on, how much progress they have made, and if and when their attention may be needed as part of another team member’s activities. This is where employee skills tracking becomes critical. Using the right software or platforms that enable you to track not only tasks but also the skills each team member is applying and developing helps create visibility and coordination. You can easily identify who is best suited for specific tasks and ensure no skill gaps hinder productivity. It is best to take advantage of collaboration tools like Trello and Slack, to help keep people on top of activities, and in fact, you may need to use both tools. Here’s why. Trello is a tool for assigning tasks and keeping track of activities, and it does that very well. Slack on the other hand focuses on team communication about activities. And, it offers many powerful features and integrations to make this process effective. Most people who use both tools conclude that you are better off using the two together. However you can start with one (preferably Trello), and include the other later on. 4. Keeping track of goals and productivity In an office setting where there are departments and managers and the like, it may be fine for employees to know just what their jobs are and how to do them the right way. Understanding how it all fits into the goals of the company is more a job for managers and executives. In most remote settings however, employees often have to wear different hats and manage themselves. Thus, you are much better off keeping team members keenly aware of the company’s short term, and even long term goals. When employees are kept in the know like this, they are able to contribute their ideas and creativity to seeing these goals attained, and if you have worked in a remote team, you know how important this is. Also, when goals are met, inform employees of this and explain how the team made it happen, and what new goals you have set if any. Using training and development platforms can further empower your team by providing ongoing upskilling opportunities tailored to remote work needs. These platforms help employees improve their competencies, adapt to new tools, and stay motivated by continuous learning, which is essential when managing remote teams. 5. Knowing time zones Consider this: A team member in the US (CST) says to another in the Philippines, “Let’s get together to discuss this by Tuesday 4PM.” If indeed this conversation takes place, although it happened on Tuesday for the person in the US, it actually happened on Wednesday for the team member in the Philippines (yes telecommuting is time travel). In a remote team I work with, we usually have to get together by 9am CST. At this time, it is already evening for some team members, while others are well into the night. So in exchanging pleasantries, hi, good morning, is quickly followed by hello, good evening to others. The importance of knowing time zones however goes far beyond pleasantries. It helps you determine when will be the best time for a meeting, or for performing certain tasks. For tasks that are not time bound, it is best to allow employees perform them within daylight hours in their time zone. Many remote teams allow for wiggle room in this manner, and this leads to productivity. 6. Getting team members to KNOW each other When you get together to discuss, what do you talk about? Goals, activities, customers? Yes, that should majorly be what you discuss, but not ALL you discuss! Remember, humans are social beings, and beyond knowing about work, we also usually want to know our team members and keep updated on the happenings in their lives. I’ve been fortunate to work in teams that value social interactions, and I can tell you, being very social does not reduce work output. Quite contrarily, it keeps employees engaged, happy, and productive. So the next time you have a group meeting, ask employees about their personal lives (if you have not been doing this), or better yet, start off by telling them something about yours. If you’ve found a special recipe that you really like, or a place you plan to spend your holiday, share it with team members and have them discuss. To build a strong remote team, you need friends, not minions. How can you apply this to your remote team? Very likely, you have already been using some of the tips shared in this post. So you can look for areas addressed here in which you are not doing so well. Do you communicate regularly, but only about business? Spice it up with some social chat. Do you make all the plans and only tell team members what they need to do? Then you may be wasting valuable brain power that could move your business from A to B. The truth is, remote work is here to stay! The stats even reveal that more and more people will be working remotely in upcoming days. Although there are some challenges in managing remote teams, these challenges hide under the mat when the advantages pay a visit. Better yet, these challenges can largely be conquered with a little effort — including using the right employee skills tracking tools and training and development platforms to keep your team aligned, skilled, and motivated. FAQ What are the biggest challenges of managing remote teams? The six major challenges are communication breakdowns, hiring the right self-starters, tracking activities and task ownership, maintaining goal alignment and productivity, navigating time zone differences, and building genuine personal connections among team members who never share an office. How should remote teams handle daily communication? Remote teams should communicate at least once daily via video or voice conference. A powerful approach is to hold a morning standup, then keep the line open for an additional hour so anyone can unmute and ask questions or share updates in real time. What traits should I look for when hiring remote workers? Look for demonstrated ability to manage time, handle tasks independently, and deliver results without constant oversight. Remote work requires self-motivation and discipline, so hiring on a trial basis is a smart way to evaluate whether a candidate can thrive outside an office. How do you track activities across a remote team? Use collaboration tools like task management and messaging platforms in tandem. Task management tools handle assignment and progress tracking, while messaging platforms support real-time communication about those tasks. Employee skills tracking software adds another layer by mapping who is best suited for which work. How do time zones affect remote team productivity? Time zone differences create scheduling conflicts and can lead to miscommunication about deadlines. The best approach is to schedule meetings during overlapping hours and allow flexible work windows so employees can complete non-time-bound tasks during their own daylight hours. Why is goal transparency important for remote teams? Remote employees often wear multiple hats and manage themselves. When they understand the company's short-term and long-term goals, they can apply their creativity and judgment to advance those goals rather than simply following task-level instructions with no broader context. How do you build personal connections on remote teams? Dedicate time in group meetings for non-work conversation. Share personal updates, ask about team members' lives, and encourage social interaction. Teams that invest in personal relationships see higher engagement, happiness, and productivity because people feel connected to colleagues, not just tasks. Are remote workers actually more productive than in-office workers? Research published in the Harvard Business Review indicates that remote workers are often more productive than in-office counterparts. This makes sense because remote work self-selects for motivated individuals who can manage their own time and environment effectively. What tools do remote teams need to succeed? At minimum, remote teams need a video conferencing tool for daily communication, a task management platform for tracking assignments and progress, and a messaging tool for real-time collaboration. Adding skills tracking software helps ensure the right people are matched to the right work. How does skills tracking help manage remote teams? Skills tracking gives managers visibility into each team member's capabilities, making it easier to assign the right tasks to the right people. It also identifies skill gaps that may be hindering productivity, so you can target training and development where it will have the most impact. --- ## The Impact of Skills Management on Business Performance URL: https://skillsdb.com/blog/the-impact-of-skills-management-on-business-performance This white paper explores the impact of skills management on companies that have implemented them. Find out how their businesses run. In our modern business climate, companies are made or broken by the amount and kind of information they use in guiding business decisions, and each day, new ways to gather data and new applications for available data are explored. In fact, the impact of skills management on business performance is enormous. Since there is a general consensus that a company’s most important asset is its people, reliable data about people’s skills and how they relate to business goals should have tremendous effects on every company. This is where skills assessment plays a crucial role in aligning employee capabilities with organizational needs. Many companies have thus implemented skills management systems, some for more than a decade now. And so, ample time has passed to assess the impact skills management has had (and can have) on business performance. A robust skills management platform helps businesses track, assess, and develop employee capabilities, ensuring that talent is aligned with strategic goals. We published a whitepaper that analyzed this topic. The paper provides an in depth view into the experiences of companies that have implemented this system, and how it has improved businesses in 4 major ways: 1. Bridging the Skills Gap 2. Effective Employee Development and Succession Planning 3. Getting the Right People into the Right Positions 4. Financial Benefits Download the whitepaper here . FAQ How does skills management impact business performance? Skills management improves business performance in four key areas: bridging skills gaps, enabling effective employee development and succession planning, placing the right people in the right positions, and delivering measurable financial benefits. Companies with skills data make better talent decisions across the board. What is a skills management platform? A skills management platform is software that helps businesses track, assess, and develop employee capabilities. It aligns individual skills with strategic business goals, giving leaders visibility into workforce strengths, gaps, and development opportunities in one centralized system. How does skills management help bridge the skills gap? By inventorying the skills your workforce currently has and comparing them against what the business needs, a skills management system makes gaps visible and actionable. Leaders can then target training, hiring, and development efforts precisely where the organization is falling short. Why is skills data important for succession planning? Succession planning requires knowing who has the competencies and leadership potential to step into critical roles. Skills management provides that data systematically rather than relying on subjective recommendations, making succession decisions more objective and future-proof. How does skills assessment align employees with business goals? Skills assessment evaluates where each employee stands relative to the competencies their role requires. When this data is connected to organizational objectives, leaders can see exactly which capabilities support strategic goals and where investment in development is needed. What financial benefits come from skills management? Skills management reduces costs by improving internal talent utilization, which decreases reliance on expensive contractors and external hires. It also reduces failed placements and turnover by ensuring people are matched to roles that fit their actual capabilities. How does skills management improve employee development? Skills management gives managers and employees a clear picture of current competency levels versus role requirements. This data transforms development from generic training programs into targeted initiatives that address specific gaps and accelerate career growth. Why should companies invest in skills management now? In today's business climate, companies are made or broken by the quality of data driving their decisions. Since people are every company's most important asset, reliable data about workforce skills and how they connect to business goals is not optional -- it is a strategic necessity. --- ## Why Every Company Should Embrace a Culture of Positive Feedback URL: https://skillsdb.com/blog/why-every-company-should-embrace-a-culture-of-positive-feedback Two weeks ago, I gave a task to my graphic designer. I explained some of the specifications and asked him to come up with a stunning design. After discussing other necessary issues, I reminded him once again that I wanted it to look amazing. The next day, I received an email about the design and went on to check it out. It looked thrown together, far from what I expected. I was furious because I knew what he was capable of, and in the heat of anger, I was about to contact him and ask why he made such a mess of the design (and that was the kindest question I had in mind, did I mention I was furious?) But then I decided to hold on for a while. Later that day, I sat down and came up with a more precise description of what I wanted. When I contacted him, I first of all thanked him for his effort and timely response to my request, and then went on to explain quite honestly that I expected something better. I pointed out some of the awesome jobs he had completed in the past and told him he can do something that good for me too. And finally, I gave him the more precise description I came up with. The next day, I received the graphic work, and it looked “amazing”, much better than I imagined it would be. I’m not sure I would have gotten the same results if I had not striven to give feedback that reminded him of what a great designer he usually was, and why he can do better than he did initially on this work. But do I have solid reason to believe that my designer performed better because I tried to remain positive? Absolutely! The power of positive feedback A new study published by Harvard Business School proves that employees perform better when they receive positive feedback. The study shows that when people are reminded of times in the past when they had performed excellently, they become more creative, make better decisions, and feel less stress. “In the study, participants visited the Harvard Decision Science Laboratory and were asked to solve problems. Approximately half of the participants were told to ask friends and family members to send them an email just prior to their participation that described a time when the participant was at his or her best. Overwhelmingly, those who read positive statements about their past actions were more creative in their approach, more successful at problem-solving and less stressed out than their counterparts. For instance, participants had three minutes to complete Duncker’s candle problem. Fifty-one percent who had read emails prior to the task were able to successfully complete it; only 19% of those who did not receive ‘best-self activation’ emails were able to solve it. Those who received praise were also significantly less stressed than the control group.” – Forbes In effect, what this study proves is what we already know: People work better when they are commended for their accomplishments. For some reason however, many people in management still believe that regularly pointing out flaws and avenues for improvement is the best way to motivate employees. The existence of a management practice that requires each employee to sit through a (mostly negative) critique of their performance every year proves this. Late last year, we published the results of a research work that revealed the major reasons why employees experience bad days at work, and the third highest reason is “Lack of praise or recognition for the work I do.” So besides degrading the quality of their work, lack of commendation could also make employees hate their job. How to foster a culture of positive feedback 1. Re-engineer your appraisal process Apparently, everyone hates yearly appraisals – employees, managers, and even HR practitioners. This management practice essentially ruins relationships around the workplace. As a result, some companies have dropped yearly appraisals and opted for performance feedback in real-time. Accenture, a global consulting firm, made the headlines last year when they announced their plans to replace yearly appraisals with timely feedback from managers. This shift is more achievable when companies adopt an employee training platform that allows real-time feedback, engagement, and coaching throughout the year. 2. Help employees focus on the tasks they did well As my personal experience and the results of the Harvard study have shown, employees perform better when they are reminded of things they did really well in the past. In essence, if you are about to start a task or a project and you want your employees to be at their best, remind them of a time when they were at their best, commend them for their contribution to the success of that past task, and express confidence that they will perform well in current tasks too. This practice is at the core of effective competency training, where strengths are reinforced through repetition and feedback. 3. Say it A common belief among people in management is that giving positive feedback to employees is not really necessary, or that it should be minimized – how wrong! There is this story of a manager who refrained from commending one of his employees for an awesome job because, well, she had done some very awesome jobs previously that week and the manager thought he had commended her enough. However, what he might have failed to note is that his previous commendations may be the reason she continued to produce stellar results. Simply put, if you think an employee has done a great job , give positive feedback it every time! Simply say it. 4. Criticize constructively There are people who believe constructive criticism has no value in manager-employee relations, I’m not one of them . I generally prefer to give (and receive) constructive criticism. Which would you prefer to hear after putting effort into a task but falling short: This is the crappiest job I’ve seen this week. I mean the stats are correct, but your presentation is laughable. Were you half asleep when you wrote this report? Or You really put a lot of effort into this report, I appreciate how carefully you worked on the stats, it’s thoroughly researched. You can however improve your explanation of the data in sections 2 and 3. Grab a copy of the report I wrote last month and study my presentation of those sections and try to come up with something great. In truth, constructive criticism which usually includes tips for improvement works better than outright, sharp cutting criticism. However, there are times when straightforward criticism is required, such as when an employee repeatedly makes a mistake or falls short despite previous corrections. When this becomes necessary, it should be given out. Employees are adults, they can handle it. 5. Encourage managers to give out spontaneous, honest commendation Some managers may be good at commending people while many others don’t even know the meaning of the word. It is best to promote a culture of commendation among managers like you promote other formal policies. Simply telling managers to commend others will hardly work though, so it’s best to remind them for a while possibly through an email at the start of each week, until it becomes a part of them. One way to achieve this on a broader scale is by using training and development platforms that prompt feedback and recognition through built-in features. 6. Encourage employees to commend each other Commendation does not always have to come from superiors to be effective. In the Harvard study considered above, the group that performed a great deal better did so because they received an email from a friend, family member, or coworker. Therefore, employees should be encouraged to honestly commend one another whenever possible. Alexander Kjerulf, the founder of Wohoo Inc, suggests that employees learn to send emails of appreciation to fellow employees. The emails should be short and personalized. A good example would be: Hi Darla, I’m just writing to thank you for the well prepared stats you presented during our last meeting. They really gave us all a clearer understanding of the tasks at hand. Regards, Mesheal What can you learn from this? Frankly, giving positive feedback isn’t easy. It takes effort to tell people around you that you value their input to the success of your activities together. But those who have embraced a culture of commendation only have good things to say about it. It may only take a few words to brighten the day of someone you work with, which, as it turns out, also brightens your day. As an individual, it is important to learn to commend others. If you are in a management position, take action to promote this culture among employees, managers, and everyone else. It clearly leads to better performance. FAQ Why does positive feedback improve employee performance? Harvard Business School research shows that when employees are reminded of past accomplishments, they become more creative, make better decisions, and experience less stress. In one study, 51 percent of participants who received positive affirmation solved a problem compared to only 19 percent who did not. How should companies replace yearly performance appraisals? Replace annual reviews with continuous, real-time feedback from managers throughout the year. Companies like Accenture have already made this shift, finding that timely feedback builds stronger relationships and drives ongoing improvement rather than creating one dreaded annual event. What is the best way to give constructive criticism? Start by acknowledging the effort and what was done well, then clearly identify what needs improvement with specific guidance on how to do it better. This approach preserves motivation while giving employees an actionable path forward, unlike sharp criticism that only demoralizes. How does lack of recognition affect employee morale? Lack of praise or recognition is one of the top three reasons employees experience bad days at work. Beyond degrading work quality, it can make employees actively dislike their jobs, increasing disengagement and turnover risk across your organization. Should employees give positive feedback to each other? Absolutely. The Harvard study found that participants performed significantly better after receiving positive emails from friends, family, or coworkers -- not just managers. Encouraging peer-to-peer appreciation through short, personalized emails or messages creates a culture of recognition at every level. How can managers build a habit of giving praise? Start by sending managers a weekly reminder to recognize someone on their team until it becomes natural behavior. Simply telling managers to commend others is not enough -- you need to systematically prompt the behavior until it becomes embedded in your management culture. Can you give too much positive feedback at work? No. A common management misconception is that employees receive "enough" praise and should be left alone. However, previous commendations are often the reason employees continue producing strong results. If someone does great work, recognize it every single time. When is direct criticism more appropriate than constructive feedback? Direct criticism is warranted when an employee repeatedly makes the same mistake despite previous constructive feedback and corrections. Employees are adults who can handle straightforward feedback when the situation calls for it, and sometimes clarity requires directness. How does positive feedback relate to employee creativity? The Harvard study demonstrated that employees who were reminded of their best past performance approached problems more creatively and solved them at significantly higher rates. Positive feedback literally activates better cognitive performance, not just better feelings. What role do training platforms play in feedback culture? Employee training platforms with built-in feedback and recognition features make it easier to deliver real-time coaching and commendation throughout the year. They systematize what would otherwise depend on individual manager initiative, creating more consistent feedback across the organization. --- ## 11 HR Blogs That Can Improve Your Career URL: https://skillsdb.com/blog/11-hr-blogs-that-can-improve-your-career In our modern, fast paced business world, few things are more powerful than information. In fact, business trends, processes, activities, and policies are constantly being updated. Those that were the rage before you signed off for the weekend may be seeing their final moments when you resume the next week. Thus, if you want to be a top performer in your field, you need to keep yourself informed. One of the best ways to do this is by engaging with quality resources that support your skills development program and competency training initiatives. Here at SkillsDB, we are always seeking ways to improve as individuals and as a company. And, one major way we achieve this is by reading, a lot of it. We even have a few blogs we follow. In addition, we can honestly say that we have benefited in many ways from the insights shared by these bloggers. Each day you work, you have to pull resources from your mental storehouse and use them to accomplish tasks and projects. It only makes sense to keep updating and growing your skillset — which is exactly what a strong skills development program aims to do. Reading online blogs dedicated to HR trends and professional growth can be a valuable part of that program. So for our blog post this week, I have put together a list of 11 HR blogs in which articles that are always worth a read are regularly published. 1. Success In HR Alan Collins, a former HR Vice President at Pepsi Co. is the founder and chief editor of this blog. In fact, he has had a long career in HR and his advice and career tips are top notch. Besides what he writes on this blog, he has written 8 books for HR professionals. 2. TLNT TLNT provides news, analysis, and opinions that can help you come to grips with current trends in HR. The blog has several contributors and multiple articles are published each day. Also, one thing you quickly notice when you view this site is how engaging it is. The writers address issues that grab at the heart and they present them in a way that makes you want to read through each article. Many of these topics tie directly into modern learning and development platforms, especially those aimed at employee engagement and upskilling. 3. Positive Sharing Positive sharing is a blog by Alexander Kjerulf, otherwise known as the chief happiness officer. True to this title, his blog is all about finding happiness, and making employees happy at work. Alexander is also the founder of Woohoo Inc, and is one of the world’s leading experts in happiness at work. Notably, he has done a good amount of study and research on workplace happiness. In addition, he presents his findings on his blog in a conversational, interesting way. 4. TalentCulture This blog publishes regular articles on topics about finding and developing top talent, being a great leader, understanding changes in HR, as well as other similar areas. The authors on this blog usually employ a light, social approach to their blog posts. This way, they make them interesting to read and yet packed full with value. 5. HR Bartender I was taken aback by the name of this blog. But, the founder, Sheryl Lauby, does give an explanation for the name. Something in the line of she being the friendly person HRMs want to communicate with or hear from about work related issues, just as workers love to see the face of a bartender after a stressful workday, and with that I agree. In fact, Sheryl’s blog posts are centered on career advice, leadership and management, and office politics. Somehow she manages to produce several articles each week on her own. For instance, each is written in a casual and informative way that makes you look forward to the next. 6. Ask A Manager The moment you open this site and see the complete title (Ask a Manager and if you don’t, I’d tell you anyway), you get the feeling you are going to have a good read. At least I did, and boy did it turn out to be true. Ask A Manager is a site where people can ask questions about HR, their career, and a host of other topics. Each question is responded to by Alison Green, a former chief of staff, and her responses are always simple, straightforward, and down to earth. You hardly see an “I don’t know what you should do in this situation” kind of response, and simply reading through previous questions and answers provides you with information that can improve your career. 7. HR Morning HR morning is a news blog for HR professionals. It provides the latest news on trends and events that are shaping the field of personnel management. Writers at HR Morning present the news as what they term “actionable insight.” In essence, you get to find out what’s new, and also what it means for you and for your business. 8. HR Examiner This is a magazine blog that focuses on the people, technology, ideas and careers of senior leaders in Human Resources and Human Capital. They have quite a few authors who publish articles, and multiple articles are published each week. The authors often come together to form a panel that takes an in-depth look into important issues and trends in HR. Their blogs are usually presented as audio files, but a transcript is produced for those who prefer to read. 9. Skills Competency Blog (SkillsDB) Here at SkillsDB, we regularly publish blog posts centered on improving the careers of our readers, and helping them become better recruiters, skill managers, and succession planners. We also look into current trends every now and then to help keep readers fully informed on what’s new and groundbreaking in HR. 10. Fist Full of Talent This is one of the most diverse and informative hr blogs on the internet. They have a group of about 30 writers who produce regular articles on a range of hr and people management topics, ranging from leadership and employee relations to recruiting, career paths, and succession. Besides articles, they also publish podcasts and videos that feature a program called the CYA Report, which they define as a “free flowing, sometimes mature discussion of HR and talent issues.” 11. HR Zone This is another site that covers a diverse range of interesting and practical hr topics. Notably, an entire section of this blog is dedicated to predicting HR trends. All articles in this section are prefixed with the phrase “Future of HR.” The major links at the top also make it clear that the articles published are meant to help HRMs become better leaders, fully engage their employees, hire and utilize top talent, etc. How Can You Use This Information? As I mentioned at the outset, at SkillsDB, we read and follow a few blogs that publish information related to our individual skills and our business. You can and should do the same, and this article helps you identify some great blogs you can follow. Of course you are only expected to choose a few that resonate with you and that publish career tips that you find most fitting. Hopefully you, like us, will quickly see the value of being fully informed of the news, trends, and career advice that blogs provide to their readers. FAQ What are the best HR blogs for career growth? Top HR blogs include TLNT for news and analysis, HR Bartender for career advice and leadership, Ask A Manager for practical Q&A, HR Morning for actionable industry news, and TalentCulture for talent development insights. Each offers a distinct perspective that helps HR professionals stay sharp and informed. Why should HR professionals read industry blogs regularly? Business trends, processes, and policies change constantly. Reading quality HR blogs keeps you informed about emerging practices, regulatory shifts, and leadership strategies so you can make better decisions and stay competitive in a fast-moving field. What makes TLNT a valuable HR resource? TLNT publishes multiple articles daily with news, analysis, and opinion on current HR trends. Its writers address engaging, real-world issues in a way that makes complex topics accessible, covering everything from recruitment to employee engagement and modern learning platforms. Who is the Ask A Manager blog for? Ask A Manager is for anyone with questions about HR, career decisions, or workplace dynamics. Alison Green, a former chief of staff, responds to reader questions with straightforward, practical advice. Reading through past Q&As alone can provide a valuable education in workplace management. How does reading HR blogs support skills development? Every workday, you draw on your professional knowledge to accomplish tasks and projects. HR blogs provide a steady stream of new insights, trends, and best practices that expand your skillset and keep your competencies current -- essentially an ongoing, informal skills development program. What does the HR Examiner blog focus on? HR Examiner is a magazine-style blog focused on people, technology, ideas, and careers of senior HR leaders. It features expert panels that take deep dives into important industry issues, with content available as both audio and written transcripts. Which HR blog focuses on workplace happiness? Positive Sharing, by Alexander Kjerulf (the "Chief Happiness Officer"), is dedicated to finding and fostering happiness at work. Kjerulf is one of the world's leading experts on workplace happiness and presents his research in a conversational, engaging style. How do I choose which HR blogs to follow? Pick a few blogs that align with your specific role and interests rather than trying to follow them all. If you focus on recruiting, prioritize talent-focused blogs. If you are in L&D, lean toward those covering skills development and training. Quality over quantity produces the best results. --- ## Developing Your Competency Framework URL: https://skillsdb.com/blog/developing-your-competency-framework It is widely known that people are the most important part of most organizations. Read this article on how to go about developing a competency framework to align your people to the greater organizational goals. Developing a Competency Framework —Linking Skills to Company Objectives Imagine a world without measurement scales. Where you cannot know your height, weight, the temperature, how much you have or need to spend, etc. – because there are no scales to measure any of that. Certainly, that would be a confusing world. Gladly, people have always found ways to graduate things into measurable quantities. Even as this is typed on my computer, there is a feature showing the word count. Not very necessary, but this just shows how important it is to measure things. However, many businesses are yet to create a measurement scale for one of the most vital factors to business success: Competency. What Is A Competency Framework? First, competency is the knowledge, skills, judgment, and personality traits that employees need to work effectively and to support business objectives. In particular, a "competency framework" defines the required "competencies" across all roles in the organization. Thus, this framework provides an easy way to measure if your people are acting competently and supporting the business goals. And, it outlines all possible adjustments. Below is a sample competency. As a company, one competency that supports our growth is “Ability to guide development with customer needs in mind.” Thus, here’s the definition for this competency as it would appear in our competency framework. Ability to Guide Development with Customer Needs in Mind This competency means that the features requested by current/potential customers are properly logged, and are considered when creating new features or updating old ones. Effective Behavior People who are effective… Ineffective Behavior People who are ineffective… Developer Collect data from customer interaction and feature suggestion pages, use surveys, analyze feature trends in other providers. Reach a decision of most necessary features based on this analysis. Start working on features on a whim, decide what they think customers would need without actually doing due research, interact with customers but take no note of their thoughts on necessary features. Technical Support Person Take note of customer feature requests during interaction, take note processes that are confusing or difficult for customers and that would be best simplified with a new feature, prioritize feature suggestion based on number of requests and sends to development. Do not log customer feature requests, work hard to create workarounds without suggesting a new feature to make things easier, send no suggestions to development. For instance, if we identify a couple of other competencies and define them this way, what we get is the SkillsDB competency framework. As you can see above, a competency framework lays out the blueprint for ‘excellent’ performance within an organization. Generally, the competency framework of an organization consists of a number of competencies that can apply to a broad number of roles within the organization. In fact, a good framework uses language that is clear enough for everyone to understand. It explains what an excellent job behavior really looks like, and what behavior would reveal a lack of competency. When a common understanding is clear, it becomes the benchmark against which the overall performance of an individual, project, team, or an entire organization is assessed and evaluated. This is also a great foundation for implementing competency assessment tools within the organization to track skill alignment and training needs. Benefits of Developing a Competency Framework for an Organization An organization that neglects to define its expected standard of performance, will become an organization where the judgment of good, bad or excellent will be highly subjective. Certainly, when a company or an organization does not have a common understanding of good, bad and excellent, its judgment cannot be fair and cannot lead to development priorities. A properly defined competency framework on the other hand, helps your company: Ensure that people work effectively and produce results. Select and recruit employees that are a strong fit for the role and organization. Focus employees on improving their performance and skills. Identify gaps in staff and individual employee competencies, and on that basis provide valuable insights for creating highly targeted development initiatives. Provide a comprehensive roadmap for employee development, career planning, employee succession, and other important development aspects. Organizations can also use this structure to roll out a competency based training program, allowing for structured and goal-oriented upskilling tailored to role-specific expectations. Clearly, a well-defined competency framework creates a unity of direction for employees on daily tasks and projects, development, and succession. The competency framework also becomes the guiding criterion for recruitment and selection. At the time of hiring new employees, a competency framework eliminates wastage of resources spent on recruiting, selecting and training the wrong people. A framework also ensures thorough assessment of an employee’s’ performance once it is implemented. In addition, these assessments give more consistent, credible and reliable results of what the employees in the organization are capable of doing. How To Develop A Competency Framework For Your Organization? There are 3 major factors that would help make the process of developing a framework successful such as: Staff Consultation: When designing a framework, it would be a mistake for HR to do all the work. Instead, the reasonable and effective approach is to involve the people who actually work in various roles. Change Management: Getting people to use a framework involves change, and as we all know, change is often resisted. It is thus wise to create a careful approach to manage change. Effective Communication: All members of the organization should be fully aware of the framework in development, the part they play, and their obligation when the framework is made available. Building the Competency Framework By now, you should already have a goal in mind for your framework. If not, that is the first thing you should establish. The purpose of your framework would determine exactly how you go about it. For example, if you were creating a framework strictly for recruiting new staff, it would be different from the one for the entire organization, including top management – one obvious reason is that expectations for new staff and top management are often different. When you have your goal clearly mapped out, the following 4 steps would take you through the process of creating the framework. Create a Lead Team A team comprising of people from all parts of the organization should be involved in this project. This team helps ensure the frameworks involves every role and aspect in the business, and correctly represents the skills, goals and behaviors across the organization. The lead team also helps to manage change in each part of the organization. Gather Information This is the most important step in creating the framework. The two best ways to gather information is by interviewing people in various roles, and using a questionnaire. Interviewing People You can conduct a group interview, or speak with a sample of people from various teams. At this step, you can ask people questions about various tasks, situations, and roles in the organization. The questions could be – “What do your best managers do? What do your best staff do? How do they behave? What do your beneficiaries and other partners say about their contact with the best managers?” – managementcentre.co.uk From these questions, you derive behavior statements, which are simple statements about best practices in a role. An example is “Our best developers take note of customer needs and use these to select future features” Using a Questionnaire If you want to have as much data as possible, it may be best to ask the opinion of all individuals about the optimal behavior in a role or situation. In that case, you can create a questionnaire containing these questions and use it for an organization-wide survey. Create the Framework First, you want to study the data gotten from the previous step. Your framework would be built on the data gathered, and the first step to building from this data is structuring and grouping the information received into understandable clusters. Separating statements into clusters The responses gotten should be analyzed and separated across distinct clusters. For example, take the following sample question and answers: Q. What do you think makes a developer effective? A1. An effective developer carefully weighs the needs of customers before deciding which new features are most important. A2. An effective developer communicates his thoughts on necessary features with other members of the team and only spends time working on a feature when the team agrees on it. If you notice, the two answers above can be grouped under two different work attribute clusters. The first can fall under under Judgment and Decision Making Cluster, while the second under People Cluster because this has to do with communication. This Civil Service Competency Framework for the UK clearly illustrates this clustering. Creating Sub Clusters When grouping items into clusters, you would likely notice that major clusters can have sub clusters. Take the example above, the second answer was grouped under People. However, this would be better categorized if it is grouped under People – Communicating. Thus, you can have other sub clusters like People – Collaborating, etc. under which other statements can be more appropriately grouped. This is also illustrated in the Civil Service framework above. After this step, you should have a clearly defined list of Clusters -> Sub clusters. And, from here, your team can define the competencies in each cluster. Here’s an example of cluster and sub-cluster groupings. PEOPLE Communicating Collaborating Managing JUDGEMENT AND DECISION MAKING Using Data Having a Long-Term Outlook Weighing Multiple Factors PERFORMANCE Achieving Commercial Gain Delivering Value for Money Delivering on Time From this grouping, you can go on to create your statements of competent behavior for each sub cluster, grouped according to the job roles in the organization (see our sample competency framework at the start of the article). When writing competency statements, it is best to keep things really simple. Use language that is not ambiguous or hard to understand, so everyone can comprehend what competent behavior means in their job role. Also, you want to ensure the competencies are in connection with business objectives. Since you already did a survey, this should be the case at this point, but you can make sure of this by having a few management level staff across departments review and make suggestions on the framework. Don’t forget to design your statements in a way that supports your competency training programs—simple, specific, and results-driven. Implement Your Framework in a Competency Management System Having a framework on paper is great – it gives the organization a clear sense of measurement. However, many things on paper do not serve a big purpose in our tech advanced world. Hence, many companies now opt to use a competency management system, in which you can define job role competencies based on your framework, and get immediate insight on how your people compare against the required competency for their role. A typical competency report lists the skills and attributes of an employee, people in a job role, department, etc, and compares this against their expected level of competency to help you visually identify gaps and training needs. If you aren't yet using SkillsDB to manage your people’s skills, training, and competencies, please sign up for a free 1-1 session with one of our competency experts. After signing up, please contact us to let us know what feature you would like to see work for your company (possibly competency in this case). Our tech support team will guide and advise you through the entire setup process. FAQ What is a competency framework? A competency framework defines the knowledge, skills, judgment, and behaviors required across all roles in an organization. It creates a common standard for measuring whether employees are performing effectively and supporting business objectives, replacing subjective assessments with clear benchmarks. Why does my organization need a competency framework? Without a framework, judgments about performance are highly subjective and inconsistent. A well-defined competency framework provides a shared understanding of what good, bad, and excellent performance looks like, enabling fair assessments, targeted development, and better hiring decisions. What are the key benefits of a competency framework? A competency framework helps ensure employees work effectively, improves recruitment by defining role-specific criteria, focuses development efforts on real gaps, provides a roadmap for career planning and succession, and creates consistent, credible performance assessments across the organization. How do I start building a competency framework? Start by defining the goal of your framework, then assemble a cross-functional lead team representing all parts of the organization. This team gathers information through interviews and questionnaires, structures the data into clusters and sub-clusters, and defines competency statements for each role. Who should be involved in developing the framework? A lead team comprising people from all parts of the organization should drive the project. HR should set guidelines and structures, but the employees who actually perform the work are the legitimate experts on the skills and behaviors their roles require. What are competency clusters and sub-clusters? Clusters are broad categories of workplace attributes like People, Judgment, or Performance. Sub-clusters break these down further -- for example, People might include Communicating, Collaborating, and Managing. This structure organizes competency statements into a clear, navigable hierarchy. How do you write effective competency statements? Use simple, unambiguous language that anyone in the organization can understand. Each statement should describe specific observable behaviors for a given role, defining both what effective performance looks like and what ineffective performance looks like. What role does change management play in implementation? Introducing a competency framework requires employees to adopt new standards and processes, which naturally meets resistance. A deliberate change management approach with clear communication about what the framework is, why it matters, and how it benefits employees is essential for adoption. How does a competency framework improve recruitment? The framework defines exactly what competencies each role requires, giving recruiters specific criteria to evaluate candidates against. This eliminates wasted resources on recruiting and training people who are not the right fit, and produces more reliable hiring outcomes. Should I implement the framework in a management system? Yes. While a paper-based framework provides clarity, implementing it in a competency management system like SkillsDB lets you define role competencies, track employee assessments against benchmarks, and instantly identify gaps and training needs across your entire workforce. What is competency-based training and how does it connect? Competency-based training is structured upskilling tied directly to the competencies defined in your framework. Instead of generic training, you deliver targeted development that addresses specific gaps for specific roles, making every training investment directly connected to business outcomes. How do competency assessment tools support the framework? Competency assessment tools allow you to systematically measure employees against the standards defined in your framework. They generate reports comparing actual competency levels to expected benchmarks, making skill gaps visible and providing data to prioritize development initiatives. --- ## 8 Tips For Awesome Skills Management URL: https://skillsdb.com/blog/8-tips-for-awesome-skills-management There was a time when a skills management system was simply a nice tool to have around; that time has passed. As early as 2003, HR professionals at IBM realized that the rapidly changing business landscape meant that companies had to inventorize the skills of their workforce if they wanted to stay ahead of the competition and drive productivity. Since then, many companies have caught on. In addition, skills inventories have become quite common and – as many businesses state – quite essential to success. Today, leveraging an effective employee skills platform has become a crucial part of strategic workforce planning. But, this kind of management is still relatively new. And, you may find it hard to get information about skills management. In fact, if you Google the phrase “Skills Management”, you’d most likely get results about “Management Skills.” And so beyond helping new clients understand how to use our system, we often also have to help them understand how to implement it in their company (to the best of our knowledge of course), as well as some best practices they should observe for better results. For our blog this week, I’d be highlighting these practices that can help you successfully implement and use your skills management system. Skills Management Best Practices 1. Ensure it is supported by senior management Before you implement a skills management system, you should secure the commitment of top management. They have to be fully convinced of the business and financial benefits the system will yield. These benefits usually come from better utilization of employee skills, better staffing for projects, more effective succession planning, and most importantly, a clear awareness of the talents needed for the success of the business, and a defined method for developing such talents. Using these and other valid points, you have to get top management to buy into the idea of a skills inventory. 2. Allow employees to define the skills needed for their job roles If HR decides to create the skills inventory without consulting employees, you may end up with a system that is understood by HR, but foreign to employees. It is only natural that those who do the job everyday will have better knowledge about the skills needed for their day to day activities. And if you ignore their opinions when creating the system, you will have a hard time convincing them to use it. “HR [needs] to get out of the business of defining the work. After all, those doing the work and those overseeing the work [are] the legitimate experts.” – SHRM Study Of IBM Of course, HR has to set the guidelines and structures for collecting skills. But, an advisory team made up of employees from the different parts of the company should suggest what goes into the skills list. 3. Avoid complexity When implementing the system, start with only those skills that are critical to the success of the business. In addition, allow your skills list to grow over time. There’s no need to try to capture every possible skill that may be related to the business all at once. You can also avoid complexity by using a step by step approach when setting up your employee skills platform. These systems usually come packed with many features that may require time and effort to setup, and if you try to implement them all at once, you may get lost in the huge amount of work involved. It is best to start from one feature and expand from there. For example, we usually tell new clients who plan to use the competency management part of our system to start by setting up the skills management part and making it good. After this is done, they can go on to setup competency management. 4. Present the system as an employee development initiative On a recent online conference, a client asked us how they can present the system to their employees without putting people on edge. This was a good question because, employees are usually skeptical when any kind of change takes place. As simple as remove the coffee maker from an office and you’d raise some eyebrows. So don’t wait for employees to conceive flawed notions about the system and then try to convince them otherwise. It is better to communicate to them that the system will be used for developing employee skills and careers so as to put everyone at ease, and make them ready to use the system. 5. Organize proper training sessions Everyone needs to understand how the system functions and how they fit into it. It will expectedly take some time for your people to become familiar with the system, but you can help them get started with proper training. A good model to follow is to train managers first and get them settled into the system, after which you should organize one or more training sessions for employees. 6. Make employees use the system No, I’m not saying “force it on them.” Rather, you can make the system central to their day to day activities in such a way that they will want to use it. For example, if you decide to select employees for projects, training, and promotions based on the skills they have entered in the system (which is indeed one of the best ways to select people), employees will want to use the system as those who do not will essentially be left behind. 7. Use it to analyze training needs The very nature of skills inventories means that they can provide the best insights into the training needs of your organization. A skills inventory can help you identify skills that are critical to your organizational goals, but are currently in short supply, and you can, and should use this data to ensure all your training efforts are positioned to help your people acquire these business critical skills. 8. Learn to use the various reporting functions Skills management systems usually offer quite a few reporting functions. Each one serves a different purpose and provides a different view of the strengths and weaknesses of your workforce. But it is all too easy to find one or two reporting functions that serve your purpose, and stick to using them without exploring others. If this sounds like you, you may be missing out on other powerful reports that can help you wrap your head around your workforce skills. Basic Considerations For Best Practices There are a ton of other factors that influence the decisions you make regarding your skills management initiative, and it will be impossible to cover them all. However, before you take any action on your skills management system, ensure it is one that will: 1. Make the system easy to set up and manage 2. Make employees use and value the system 3. Earn you the continued support of top management FAQ What are the best practices for skills management? The eight core best practices are: secure senior management support, let employees define their own skills, avoid complexity by starting small, present the system as a development initiative, organize proper training sessions, make the system central to daily work, use it for training needs analysis, and explore all reporting functions. Why is senior management buy-in critical for skills management? Without top-level commitment, skills management initiatives stall. Senior leaders need to understand the financial and operational benefits -- better talent utilization, smarter project staffing, effective succession planning -- so they champion the system and allocate the resources it needs to succeed. Should employees help define their own skills inventory? Yes. Employees who do the work daily are the legitimate experts on the skills their roles require. If HR creates the inventory without consulting them, you end up with a system that makes sense to HR but feels foreign to the people who actually need to use it. How do I avoid complexity when implementing skills management? Start with only business-critical skills and let your inventory grow over time. Take a step-by-step approach to feature setup rather than implementing everything at once. For example, get skills management solid before layering on competency management or assessments. How should I present the system to employees? Frame it as an employee development initiative from the start. Do not wait for employees to develop their own assumptions about why the system exists. Proactive communication that the system is for developing skills and careers puts people at ease and drives adoption. What is the best way to train employees on the system? Train managers first and get them comfortable with the system, then organize one or more training sessions for employees. This cascading approach gives managers the knowledge to support their teams and creates champions throughout the organization. How do I drive employee adoption of skills management? Make the system central to decisions that matter to employees -- project assignments, training opportunities, and promotions. When people see that their skills profile directly influences their career trajectory, they are naturally motivated to keep it current and accurate. How does skills management support training needs analysis? A skills inventory reveals which business-critical skills are in short supply across your workforce. This data lets you direct training budgets toward the specific skills gaps that matter most, replacing guesswork with evidence-based decisions about where to invest in development. Why should I explore all reporting functions in the system? Skills management platforms typically offer multiple reporting views, each providing different insight into workforce strengths and weaknesses. Relying on just one or two reports means missing perspectives that could reveal critical gaps or untapped capabilities. What is an employee skills platform used for? An employee skills platform like SkillsDB centralizes the tracking, assessment, and development of workforce skills. It supports strategic workforce planning by giving leaders real-time visibility into who has what skills, where gaps exist, and how to close them through targeted development. --- ## Poor Recruitment Practices You Should Absolutely Avoid URL: https://skillsdb.com/blog/poor-recruitment-practices-you-should-absolutely-avoid Recruitment candidates are customers too. A poor recruitment process could thus mean loss of customers in the form of candidates who are pissed off, and friends and relatives of such candidates who learn to avoid your brand in sympathy. Just as you wouldn’t want to go back to a shop if you were treated badly, a candidate who has had a bad experience during recruitment may avoid further contact with the company involved. David Leigh, chief executive of the psychometric testing firm SHL, put it this way: “A bad recruitment experience is at least as damaging as a bad consumer experience in store.” And SHL does have the data to back this statement. A survey they conducted among some 1600 UK adults revealed that poor recruitment practices could cost your company quite a lot. Close to a quarter of the respondents had suffered 2 or 3 bad recruitment experiences, and some 6% had suffered 5 or 6. Of these, some 18% chose not to do any further business with the company at fault. This value is even higher (28%) for people between the ages of 25 – 34. A mammoth 77% said that if a friend or family member has had a poor recruitment experience, it will deter them from being or remaining customers of that business. A person who has never passed through a poor recruitment process may not be able to identify with the people polled in this study, but I can because I have. I was once shortlisted for a job, contacted by the hiring manager and informed of the “many things” I needed to prepare, and then completely forgotten about. Now I wouldn’t use this company’s products or services, not because I’m resentful, but because this experience has ingrained in me the belief that their customer service will be no better than their recruitment experience, whether this is true or not. It is quite clear then that poor recruitment practices can harm a business, and according to the study quoted above, the top four of such practices indicated by respondents are: 1. Not being told they had been unsuccessful (46%). 2. Lack of feedback about their application (39%). 3. Not acknowledging receipt of their application (39%), and 4. Not receiving feedback even after completing an interview (37%). SHL however performed another survey, this time from the perspective of recruiters. Of the 500 professional recruiters surveyed, 25% felt overstretched due to the rise in the number of people applying for jobs. Of these, 1 in 5 could not find the time to inform candidates that their applications had been received, and some 15% were too busy to inform candidates that their applications were unsuccessful. Clearly, recruiters have not simply decided to abandon courtesy. In some instances, it is the current increase in job applications that has brought recruitment practices to this nadir. Nonetheless, if 1 in 5 could not find time to inform candidates, this means the other 4 who were also overstretched, found the time to dignify candidates with a response. So, although the workload on recruiters is appreciated, the fact remains that those who are not doing so well as per the four complaints above may need to give more attention to the recruitment process, and how well candidates are kept in the loop through effective competency assessment and communication. This is actually more important than many realize. A short while before the experience I mentioned above occurred, I entered into a week-long recruitment process with a different company. But due to some unforeseen events at the start of the week, I wasn’t able to meet their deadlines (but still had a chance to get the job). At the end however, I received a kind email informing me that I didn’t make the cut. After this experience, I would still gladly use, and recommend this company’s products to others, and the difference between this experience and the one above is (would you believe it) a nice email. In our world of templates and mass emailing, keeping candidates informed really isn’t so hard. A candidate doesn’t necessarily need their name mentioned in a rejection email to get the point. Thus you can create a simple email template that says “Dear Applicant, We are sorry to inform you that………” and then mass email this template to those who didn’t make the cut. This way, you will only need a few minutes to reach out to candidates each time. Of course, if you can personalize the email, all the better. The underlying point remains that candidates should not be left in the dark. As Angela Baron of the Chartered Institute of Personnel and Development puts it: “A nice e-mail doesn’t cost much…… People really get upset when they invest a lot of time and energy in an application and hear nothing.” Worse yet, although “a nice e-mail doesn’t cost much”, the lack thereof could cost your company tremendously in lost customers. An efficient recruitment process often integrates tools such as employee skills tracking to maintain visibility over candidate progress and ensure timely communication. Incorporating a solid competency based training program after hiring can also improve employee retention by addressing skill gaps early on and boosting engagement. FAQ How do poor recruitment practices affect a company? Poor recruitment practices directly cost companies customers. Research shows 18% of candidates who had bad recruitment experiences stopped doing business with the offending company, and 77% said a friend or family member's bad experience would deter them too. What are the most common recruitment complaints from candidates? The top four complaints are not being told they were unsuccessful (46%), lack of feedback on their application (39%), not acknowledging receipt of the application (39%), and no feedback after completing an interview (37%). All four boil down to one issue: leaving candidates in the dark. Why do recruiters fail to communicate with candidates? Many recruiters are overstretched due to rising application volumes. A survey of 500 professional recruiters found 25% felt overloaded, with 1 in 5 unable to find time to acknowledge applications and 15% too busy to send rejection notices. Does a bad hiring experience really lose customers? Yes. SHL research across 1,600 UK adults confirmed that candidates who experience poor recruitment often avoid the company as consumers. The effect is especially pronounced among 25-34 year olds, where 28% chose to end their customer relationship. What is the easiest fix for poor candidate communication? A simple email template. You can create a brief, respectful message like "Dear Applicant, we regret to inform you..." and send it in bulk to unsuccessful candidates. It takes minutes and prevents the reputational damage of silence. How does candidate experience impact employer brand long-term? Candidates who are ignored form lasting negative impressions that extend beyond recruitment. They associate poor hiring communication with poor customer service, and they share that perception with friends and family, amplifying the brand damage. Should rejection emails be personalized for each candidate? Personalization is ideal but not required. Even a generic template acknowledgment is vastly better than silence. The key is that every candidate receives some form of response so they are not left wondering about the status of their application. How can skills tracking improve the recruitment process? Employee skills tracking tools maintain visibility over candidate progress and ensure timely communication throughout the hiring pipeline. After hiring, competency-based training programs address skill gaps early, boosting both engagement and retention. What percentage of candidates experience multiple bad recruitments? Nearly a quarter of respondents reported suffering two or three bad recruitment experiences, and about 6% had endured five or six. These repeated negative encounters compound the reputational cost for employers across the market. How can companies balance high application volumes with candidate courtesy? Automation is the answer. Template-based mass emails, applicant tracking systems, and structured communication workflows let even overstretched recruiters acknowledge every application. If four out of five overloaded recruiters still find time to respond, it is a solvable problem. --- ## Best Practices in Skills Management Techniques URL: https://skillsdb.com/blog/best-practices-in-skills-management-techniques We want to be competent in everything we do. We spend years, trying to get a degree in one or more disciplines. However, one day, we suddenly realize that something is wrong. We fail to cope with even the simplest workplace tasks, and the employer does not look very satisfied with our work. This is when, most probably, for the first time in our lives, we suddenly realize the importance of being competent. This is when we suddenly understand how important it is to be able to identify and close the existing competency gaps. What is competency? We often take its meaning for granted. However, a competency is a complex set of the knowledge and skills needed by employees to successfully cope with their workplace tasks. Competencies may include one’s talent or can be limited to the skills and knowledge acquired during one’s lifetime. Organizations must constantly analyze the talents and competencies of their employees, to make sure that their skills match the changeable workplace requirements. Every employee must be able to define his/her competency gaps. The process is quite simple and straightforward. Begin with identifying the most important skills and knowledge required to do your job well. You can review the organizational policies or industry standards pertaining to your job. Try to be detailed in your competency gap analysis . Do not limit yourself to general competencies. Make sure you identify the most general competencies related to your job, as well as the specific competencies that are required at your level of professional performance. Also, take a look at the competencies required in your industry or business field. These may differ from the competencies required in other businesses and organizations. Now check your competency and its level. Use a simple 5-level scale to estimate your proficiency in each identified competency. Now see where you score below 3 and try to see which competencies are still missing. For example, you may see that your organization needs a HR manager with a good knowledge of finance. You may be good at HR but lack appropriate financial management skills. This is where you find a competency gap you need to close. This is where you start your journey to personal and career growth. Some organizations use HRD software to identify competency gaps. The use of HRD software reduces the time and costs of competency gap analyses. However, only the most professional HR managers can use this type of software. The fact is that the information use for this type of software must be appropriate and accurate. HR managers should think twice before entering this or that piece of information into their HRD system. SkillsDB allows you to search for qualified individuals who have skills needed for certain jobs or projects. Identify gaps where no one has the necessary skills. Identify training needs so that training plans can be created. Provides a basis for discussion with individuals for career development. Lastly it include a Training Management feature which allows you to schedule, track, and report on your staff’s training activities. With just a few mouse clicks you can track resource/employee skills, measure performance, search for people, find skill gaps, review analytic reports, and more! Improve your skills and develop new competencies through training and participation in personal development programs. There is no better opportunity to develop and improve existing competencies than training programs. Organizations invest millions of dollars in the development programs that enhance employee competencies and skills. Find a program that meets your needs and matches your expectations, and you will never regret it! FAQ What is a competency gap and why does it matter? A competency gap is the difference between the skills an employee currently has and the skills required for their role. Identifying these gaps is critical because unaddressed deficiencies lead to poor performance, missed business objectives, and stalled career growth. How do you perform a competency gap analysis? Start by identifying the key skills and knowledge required for the role, referencing organizational policies and industry standards. Then rate your proficiency on a 1-5 scale for each competency. Any score below 3 signals a gap that needs a development plan. What is the difference between competency and skill? A competency is a broader set of knowledge, skills, and behaviors needed to perform a job effectively. Skills are specific learned abilities that form part of a competency. Organizations need to track both to get a complete picture of workforce capability. How can HRD software help with skills management? HRD software reduces the time and cost of competency gap analyses by centralizing skills data and automating assessments. However, the quality of output depends entirely on the accuracy of the data entered, so HR managers must be diligent about data integrity. What can SkillsDB do for skills management? SkillsDB lets you search for qualified individuals by skill, identify gaps where no one has the necessary capabilities, and create targeted training plans. It also includes training management features to schedule, track, and report on employee development activities. Why should employees rate their own skills? Self-assessment gives employees ownership of their development and surfaces hidden competencies that managers may not be aware of. When combined with manager assessments, it creates a more complete and accurate picture of workforce capabilities. How do you close a competency gap effectively? The most effective approach is targeted training and personal development programs aligned to the specific gaps identified. Organizations invest significantly in these programs because closing gaps improves individual performance and directly supports business outcomes. Should gap analysis cover general and specific competencies? Yes. A thorough gap analysis examines both general competencies required for any role at your level and the specific technical or functional competencies unique to your position and industry. Limiting analysis to only one type leaves blind spots in your development plan. How often should organizations conduct skills assessments? Organizations should conduct skills assessments regularly because workplace requirements change constantly. A one-time assessment quickly becomes outdated. Continuous analysis ensures that skills data stays current and that training investments target the right gaps. What role does training management play in skills development? Training management connects gap analysis to action by letting organizations schedule, track, and measure the impact of development activities. Without it, identified gaps remain theoretical. With it, you create a closed loop from assessment to improvement. --- ## 10 Tips For Becoming A Successful Personnel Manager URL: https://skillsdb.com/blog/10-tips-for-becoming-a-successful-personnel-manager Ask any CEO what they consider their most important resource and the response you are likely to get is “people.” This viewpoint, which cannot be more correct (in my opinion), implies that personnel managers who are tasked with managing this most important resource can greatly impact a company with their programs and policies. In fact, a group of CEOs who were interviewed by Human Resource Professionals Association (HRPA) stated that the role of personnel managers is critical to business success. We can expand on that to conclude that successful personnel managers are a major building block for successful companies. And so, for our blog this week, I have put together some of the best tips for Personnel Management success, with the aim of making you the personnel manager that every company wants. These tips include excerpts from the book “Best Kept HR Secrets” , by Alan Collins, former VP of Human Resources of PepsiCo. Let’s jump right in. 1. Know The Business This is one point every resource seems to agree on. Personnel managers who understand the business are better able to tailor their practices and policies to the overall business objective. Instead of being focused on keeping everybody in their best behavior, they are actively conscious of creating and sustaining a workforce that helps the business succeed. As one CEO puts it, Personnel Managers “need to map out HR organization strategy to the business strategy—do we have the organization design and people to get there? If not, what’s the plan?” This is where integrating tools like a talent management software can help in aligning the right people to strategic needs. 2. Go Easy On Legislation And Policies This point complements the one above. In order to give more attention to business priorities, a skillful personnel manager focuses less on laws and policies, many of which may have limited business value. 3. Develop “An Eye” For Top Talent There are many articles and books that contain information on how you can do this. We even published one in July that highlighted 7 important interview questions that can help you recruit the best. Even if you had been doing pretty well in hiring, you want to continue to improve your ability to attract and employ the right talent, as this is crucial. If a personnel manager brings people into a company who repeatedly turn out to be “not very bright bulbs,” his/her credibility will suffer. Conversely, if you can bring in and retain the right talent, you become a key player in moving your company towards its goals and objectives. To track progress and improve hiring outcomes, consider using employee skills tracking to monitor and analyze team capabilities over time. 4. Learn To Communicate And Recruit With Social Media “A very strong trend expressed spontaneously and frequently by CEOs was the expectation that HR have a solid grasp on how to use social media to communicate with and recruit employees.” – HRPA Report You can hardly become a successful Personnel manager in this era if you do not learn to use modern talent goldmines such as Linkedin, Xing, TalkBizNow, and other business social networks. 5. Start Your Own Blog Many “ordinary business people” (if I’m permitted to use that phrase) have quickly become successful in their fields because they picked up their computers and started blogging. As soon as people begin to look to your blog post for career tips and advice, you go from being just another worker, to an authority in the field. And as your blog grows, so does your reputation. It may not be long before your name starts getting mentioned in other popular blogs and websites. The best part is, getting started isn’t really hard. You can start your blog by following this tutorial. 6. Request For And Appreciate Feedback Ask employees what they think about any processes or policies you have put in place. And don’t be put off by negative feedback. Even if an employee’s view or suggestion is impractical or overly critical, receive it graciously and thank the person for contributing. The best part is, considering the viewpoint of employees will help you create policies and programs that work better, and would be more readily accepted. This is the exact reason companies treasure and act on feedback from the customers who use their products and services. Beside employees, feedback can come from others who are experienced and in a position to offer professional tips, such as a mentor, or a company executive. 7. Update Yourself Regularly on Personnel Management Trends Google the phrase “personnel management trends” and you will find a number of articles listing what’s hot. Who knows, that program you are thinking of implementing may be considered “so last year” by big names in the field. A successful personnel manager needs to know how things are being done right now, what new software packages are increasing employee productivity, how new laws affect employee agreements and policies, etc. Incorporating a structured skills development program into your team’s training strategy can give your workforce the competitive edge it needs to stay current and agile. 8. Learn To Predict Trends Besides keeping up with current trends, you should also be able to foresee how current events could give rise to future workforce and business productivity trends. “[Personnel Managers] are expected to forecast the social and people trends that will impact the business. ‘Be like Wayne Gretzky,’ said one CEO. ‘Know where the puck will be and help me get there before it.’ “[CEOs] want HR to translate trends into valuable opportunities for the company, preparing the workforce, as one CEO said, ‘to drive more productivity in the business.’” – HRPA Report 9. Specialize It is good to have adequate knowledge on the various aspects of people management. However, you don’t want to be the person who is just average at everything. There should be one aspect you know so well, people consult you when they need advice. 10. Fill Your HR Team With People Who Are As Good As, Or A Little Better Than You Are ”David Ogilvy, the well-known advertising wizard who founded the Ogilvy & Mather advertising agency, never spent a day in HR, but had an orientation practice that all HR leaders would appreciate. He established a wonderful tradition of welcoming new leaders in his organization with a gift of five wooden dolls, each smaller than the other, one inside the other. “When the recipient finally gets to the fifth little doll, the smallest doll, and opens it, he finds the message: ‘If each of us hires people who are smaller than we are, we shall become a company of dwarfs, but if each of us hires people who are bigger than we are, we shall become a company of giants.’” – Alan Collins (Best Kept HR Secrets.) Sources: CEO Perspective Research Highlight – HRPA Best Kept HR Secrets – Alan Collins Paulsohn.org FAQ What makes a personnel manager successful in business? Successful personnel managers understand the business strategy and align HR programs to support it. Instead of focusing solely on compliance and policies, they actively build a workforce that drives company goals and contribute directly to business outcomes. Why should HR managers understand the business strategy? Personnel managers who understand the business can map HR strategy to company objectives and identify whether the organization has the right people to execute. Without this alignment, HR operates in a silo and misses opportunities to drive real impact. How can personnel managers identify top talent effectively? Develop a systematic approach to talent assessment using structured interview questions that reveal skills, purpose alignment, and cultural fit. Track hiring outcomes over time with employee skills tracking tools to continuously refine your talent identification process. Why is social media important for modern recruiters? CEOs increasingly expect HR to leverage platforms like LinkedIn and other business networks for recruiting and employer branding. Personnel managers who cannot use social media effectively are missing the primary channels where top talent discovers and evaluates opportunities. How does employee feedback improve HR programs? Soliciting feedback from employees helps you create policies and programs that actually work and gain broader acceptance. Negative feedback is especially valuable because it reveals blind spots. The same principle applies to how companies use customer feedback to improve products. Should personnel managers specialize in one HR area? Yes. While broad knowledge across HR functions is important, having deep expertise in one area makes you the go-to authority. Specialization builds your credibility and career trajectory far more than being average at everything. How can HR leaders predict future workforce trends? Stay current on industry developments and practice connecting current events to potential workforce impacts. CEOs expect HR to forecast social and people trends and translate them into strategic opportunities, much like Wayne Gretzky skating to where the puck will be. Why should personnel managers start a professional blog? Blogging establishes you as a thought leader in HR, which elevates your reputation and career. As professionals begin seeking your insights for career tips and advice, you transition from practitioner to recognized authority in the field. What is the best hiring philosophy for HR teams? Hire people who are as good as or better than you are. As David Ogilvy famously said, hiring people smaller than you creates a company of dwarfs, while hiring people bigger than you creates a company of giants. This principle applies directly to building high-performing HR teams. How does talent management software help personnel managers? Talent management software helps align the right people to strategic needs by centralizing skills data, tracking development progress, and surfacing capability gaps. It gives personnel managers the data-driven insights needed to make workforce decisions that support business objectives. --- ## 7 Important Interview Questions You Probably Aren't Asking URL: https://skillsdb.com/blog/7-important-interview-questions-you-probably-arent-asking Asking the right questions will help get the right talents into your company. But with so many possible interview questions available, how can you narrow down on some of the best. Recruiting and training new employees costs a wad of company dollars and resources. Add the fact that about 46% of hires wash out within the first 18 months , and you begin to see why you need to be sure, every time, that you are hiring the right candidate. While the right candidate should be someone who has the skills and experience needed for the position, other factors come into play in determining if this is someone who will also stay with the company. An interview with prospective candidates no doubt provides the golden opportunity to make this decision. Truth be told though, there is nothing fun about interviews, not for the interviewer, and certainly not for the candidate. Even after reading this article, interviews will still not be fun. But they will be more effective because in here, we have zoned-in on some of the most important and revealing interview questions. 1. How will your skills and experience enable you to fulfill the requirements of this position? Note how this question is worded. The aim is to get candidates talking about their skills and experience. It is one thing to write a set of skills on a resume, and quite another to show how the various facets of a skill will fit into the various requirements of a job position, and that is why this question is so important. It gives candidates an opportunity to put their skills into dynamic situations and show how deeply rooted they really are. To make this question more effective, you might mention a unique situation, read out a few skills from the candidate’s resume, and ask how they will use these skills to handle the situation. 2. Mention five work related activities you really enjoy doing. The purpose of this question is to establish ‘purpose’ (this will make more sense in a bit.) A Forbes article that focused solely on this question phrases it this way – “When in your life have you been so passionately focused on an activity that you lost track of time, and what were you doing?” This line of questioning is important because candidates are naturally more suitable for a position if their passion and purpose align with that of the position and company. Asking candidates to list work related activities they enjoy doing, possibly up to the point of losing track of time is a great way to know their passion and purpose, and if these fit into the activities of the open position. If they do fit, you can be fairly certain this is a candidate who will work, not just for the next paycheck, but to see the company succeed. 3. Walk me through the first five things you would do if you got this job Kristi Hedges, a Leadership Development Consultant stated (and we very much agree) that this question can help you understand some of a candidate’s work-related qualities, such as “Strategic Thinking, Prioritization Skills, and Execution Style.” 4. Why should we hire you? Be prepared to get a wide range of responses on this one. Some candidates may even consider “Because I’m smart” to be good enough. One reason this question is so important is how challenging it is. It prompts candidates to market themselves and show exactly why they are a better choice than everybody else. And a candidate’s self-marketing pitch is vital in selecting the right candidate from the torrent of applications you get for each open position. It helps you see what this candidate brings to the table that others might not. In the process, you also get to gauge the candidate’s confidence and self-awareness – qualities that are important for strong careers. 5. Have you noticed anything about the company that you think should be improved? Please explain. If the response to this question is “Not at the moment”, it doesn’t mean the person is not the right candidate. It often takes time to understand how a business works, and how it should be improved. In fact, a candidate who responds “No” is far better than one who utters gibberish instead. However, if a candidate takes a moment to arrange his thoughts, and then articulately explains where your company sucks, and what can be done to make things better, you’ve got yourself a winner. 6. What are your weaknesses? There could hardly be a better question to gauge a person’s attitude and honesty. If a candidate cannot think of one single weakness they possess, it is likely because their weaknesses are deal breakers, and they have decided to keep them all hidden. Then again, for those who are honest enough to respond with actual weaknesses, if the response is something like “I feel sleepy 23 hours a day”, then you can understand why some people choose to say they’re perfect instead. With a weakness like this, a candidate is not getting this or any other job until something is done to change the situation. And so above all else, this question helps you identify weaknesses that would make a person unsuitable for the job. 7. Talk about a time that you took a risk and failed, and one where you took a risk and succeeded. What was the difference? We want to believe you are recruiting workers who will stay with your company, and can grow to become leaders. That is why this question found a spot on our top 7 list. Leaders take decisions, often involving a fair amount of risk. A new recruit who plans to grow with the company should thus show a fair amount of entrepreneurship. (Read this blog post to find out how to prepare employees to handle leadership positions from the beginning of their careers.) In her article , Kristi suggests that you ask this question to identify a candidate’s “risk-taking ability and tolerance, self-awareness, honesty, and conceptual thinking.” Yes, the right questions can help you get the right candidate Factually, you cannot be completely certain each time you hire that you made the right choice, it just doesn’t work that way. But if your interview questions are able to reveal, among other things, that the candidate truly has the necessary skills, and that their purpose aligns with the position and company, you have a much better shot at recruiting the right fit. FAQ What are the best interview questions for hiring? The most effective interview questions probe skills application, purpose alignment, strategic thinking, self-awareness, and risk tolerance. Questions like "How will your skills fulfill this role's requirements?" and "Walk me through your first five actions" reveal far more than generic prompts. Why do 46% of new hires fail within 18 months? Most early-tenure failures happen because the interview process did not adequately assess purpose alignment, cultural fit, and practical capabilities. Resumes show credentials on paper, but only well-crafted interview questions reveal whether a candidate will thrive in the actual role. How do you assess candidate skills during an interview? Ask candidates to explain how their specific skills apply to real scenarios from the role, not just list them. Presenting a unique situation and asking how they would use their stated skills tests depth of knowledge and practical application far better than resume review alone. Why ask candidates about their work passions? Understanding what work activities a candidate loses track of time doing reveals their intrinsic motivation. Candidates whose passions align with the role's core activities are more likely to stay engaged, perform well, and remain with the company long-term. What does "walk me through your first five steps" reveal? This question exposes a candidate's strategic thinking, prioritization skills, and execution style. It shows whether they approach a new role with structure and intentionality or would simply react to whatever lands on their desk. How should candidates answer "why should we hire you"? Strong candidates articulate what they uniquely bring to the table compared to other applicants. This question tests self-awareness, confidence, and the ability to self-market, which are all qualities that indicate a candidate who will advocate effectively for the company as well. Why ask interview candidates about their weaknesses? The weaknesses question gauges honesty and self-awareness. Candidates who claim to have no weaknesses are likely hiding deal-breakers, while those who share genuine areas for improvement demonstrate the kind of candor that builds trust and enables growth. How do risk-taking questions help evaluate candidates? Asking about times a candidate took risks and failed or succeeded reveals their entrepreneurial thinking, decision-making process, and resilience. These qualities matter because you want hires who can grow into leadership roles and handle ambiguity. What makes a structured interview process more effective? Structured interviews with consistent, purposeful questions let you compare candidates objectively against the same criteria. Random questions produce random results. Targeted questions around skills, purpose, and judgment consistently surface the strongest candidates. Can interview questions predict long-term employee success? No interview guarantees a perfect hire, but the right questions dramatically improve your odds. When you can confirm that a candidate's skills are genuine, their purpose aligns with the role, and their judgment is sound, you have a much stronger basis for a successful hire. --- ## Why Do Companies Use Skill Management Systems? URL: https://skillsdb.com/blog/why-do-companies-use-skill-management-systems “What are you trying to accomplish with our system?” If you ever plan to book a demo with us, you can be fairly certain this is one of the first questions we will be asking you, hopefully after pleasantries. We often receive requests for demos from business people who want to find out how our skills management platform can help them with their requirements. Today, we'll share some of the most basic and popular use cases of our skill management system, based on what our clients want to accomplish with it. It’ll give you an idea of what other companies are using skills management for, and why it has become quite popular. And if you were looking for reasons to justify implementation of skills management in your company, you’ve come to the right place. # 1 – We need a way to manage and score employee skills Many companies simply need a way to know who has what skill, and how good they are at it. A company with hundreds or thousands of employees can hardly make the most use of its talents if they do not make an effort to keep their skills list organized. Many employees have multiple skills and talents – much of which may only come to light when employees are asked to rate themselves. Here’s a common scenario – Kerry, Julia, and Mark were hired for their knowledge of the web and were assigned web management tasks. However, they also know how to craft delightful newsletters, but since this was not required for their job, they kept it to themselves.Their company which has over 3,000 workers is in need of someone to assist in their marketing efforts by creating newsletters. They decide to hire from the outside. Can you imagine how many such superfluous hires may be taking place in a company? Many of our clients can. Companies have thus opted for skills management that provides a way for employees to score themselves so as to get their people into the right activities. # 2 – We want managers to be able to rate employee skills This is another common requirement we get during demos, and for good reason. While employee self-assessment is great, a second opinion is usually needed to help ensure the data in the system is accurate. That is where manager assessment comes in. Surely, we believe employees will rate themselves properly – nobody wants to rate himself an expert only to be given tasks he knows nothing about. However, we (and our clients) also recognize that people may not always be the best judge of their abilities. Manager scoring is thus required to combat both overly modest and overly confident ratings. Let’s say a worker gives himself a 3 on a skill, but the manager has worked with this person and realizes he is actually more skilled that he credits himself, the manager can then rate him a 5 on the skill and thus ensure he engages in activities suitable for his skill level. The Manager Rating feature in SkillsDB is single blind, which means employees cannot see the scores assigned to them by managers. Note: A manager’s rating of an employee does not overwrite the employee’s rating of themselves. They are both available for use and a manager or admin performing an evaluation can decide to use either or both. # 3 – We need a way to search among our employees for people with required skills Many companies ask for this feature so they can make effective plans for upcoming projects. Others, so they can get the right people into current projects. We can surely see the sense in that – selecting the wrong people for a project could tank it even before it starts. For such clients, we gladly demonstrate how our Expert Search feature fills their use case. Let’s say you need five people who are expert in project management, and can speak some Spanish. You simply select both criteria, set the level of competency you want for each, and click search. The system searches among your employees for those who have the skills and skill levels you selected and returns the list for you to choose from. Besides skills, employees can also be sought based on certifications. And so if you want the selection above to only include experts in project management who are PMP certified, you add this to the criteria and the results are limited accordingly. # 4 – We want to be able to generate skills reports for individuals, departments, or the whole company How much of this skill do we have? How much do we need? Who are close to having the necessary skills for this upcoming project so they can be trained? What are our skill gaps and how can we bridge them? Which employees have certifications that are expiring soon? These are just some of the skill-related questions that could arise in an organization, and many of our clients know it is vital to have a precise way to get the answers. SkillsDB offers 20 different reporting options to help you do just that. The reporting tool we feature most often to our clients during demos is the advanced analytics module. This module offers a drag and drop function that allows you create custom reports by simply dragging and dropping filters. These reports do come in handy – whether for discussing with employees about their career, assessing a department or the entire company, creating outstanding proposals, or acing that presentation. And we know how much you love charts – I mean, why represent information only in tables when it can also be done with lines and rectangles and pies right? So when our clients request it, we show them our reporting functions that can also be displayed as graphical charts. Other Use Cases We want to be able to schedule and track employee training: Keeping track of training attended by employees complements the skills management process. This is yet another way to know precisely how proficient employees are, and what roles are suitable for them. Our skills development platform supports such goals by helping align employee capabilities with business needs. We need a way to know if workers are competent enough for their job position: SkillsDB has an entire module just for this purpose. Employees can be compared against their job position to see if they are competent enough, or against an open job position to determine if they are suitable for promotion. FAQ What is a skill management system used for? A skill management system centralizes employee skills data so organizations can track who has what capabilities and at what proficiency level. Common use cases include skills scoring, manager assessments, expert search, gap analysis , and workforce reporting. Why do companies need to track employee skills? Companies with hundreds or thousands of employees often have hidden talents going unused. Without a skills inventory, organizations make unnecessary external hires when qualified internal candidates already exist, wasting budget and missing internal mobility opportunities. How does employee self-assessment work in SkillsDB? Employees rate their own proficiency across defined skills, surfacing capabilities that may not appear in their job description. This self-assessment data creates a baseline that, when combined with manager ratings, gives the organization an accurate and comprehensive skills inventory. Why do managers need to rate employee skills separately? Manager assessments provide a second perspective to balance overly modest or overly confident self-ratings. In SkillsDB, manager ratings are single-blind, meaning employees cannot see their manager's scores, and both ratings coexist without overwriting each other. How does expert search help with project staffing? Expert search lets you find employees who match specific skill and certification criteria at defined proficiency levels. You select the required skills, set minimum competency thresholds, and the system returns qualified candidates, eliminating guesswork from project staffing decisions. What kind of skills reports can organizations generate? SkillsDB offers 20 different reporting options covering individuals, departments, or the entire company. The advanced analytics module features drag-and-drop custom report building and graphical chart displays for gap analysis, certification tracking, and workforce planning. How does skills management prevent unnecessary external hiring? By maintaining a searchable inventory of all employee skills, organizations discover internal candidates with relevant capabilities before looking outside. This reduces recruitment costs, accelerates staffing timelines, and improves retention by giving existing employees growth opportunities. Can skills management systems track employee training too? Yes. Training tracking complements skills management by recording what development activities employees have completed. This provides another data point for assessing proficiency and helps ensure that employees are placed in roles matching their verified skill levels. How do skills systems support employee career development? Skills management platforms compare an employee's current competencies against the requirements of target roles, revealing specific gaps. These gaps then inform personalized development plans, giving employees a clear path to advancement and giving managers data to guide promotion decisions. What is the business case for implementing skills management? The business case centers on workforce optimization: reducing redundant hiring, staffing projects with the right people, identifying training needs before they become performance problems, and making data-driven decisions about talent deployment. The ROI compounds as your skills data matures. --- # Product Documentation Full product documentation is available at https://help.skillsdb.com --- ## Authentication URL: https://help.skillsdb.com/api-docs/authentication Quick Summary: SkillsDB uses Private-Key JWT authentication — you generate a key pair, register the public key with SkillsDB, and sign a short-lived JWT with your private key on every request. We support Private-Key JWT (Client-Signed) Authentication, where the client - you - generates its own asymmetric key-pair, registers the public key + signature algorithm with our platform once, and then signs a short-lived JSON Web Token (JWT) with the private key on every request. Our API authenticates the request by verifying the JWT’s signature against the stored public key—no shared secret ever leaves your system. Here is the step by step process that will be followed ​ Provide SkillsDB the Public Key The client organization will need to provide the following to SkillsDB: Public Key: This needs to be provided most probably in PEM Format. ----BEGIN PUBLIC KEY----- MIIBIjANBg…. -----END PUBLIC KEY----- Signature Algorithm Name: The name of the algorithm used to sign the JWTs such as RS256 , HS256 ​ SkillsDB Provides Your Company ID The JWT payload includes a field called company_id , which must be acquired from SkillsDB. This is a unique identifier that identifies your company and is a must in the JWT payload. ​ JWT Payload Expected Format SkillsDB expects the following attributes in the payload of the JWT: { "external_system_email" : "maira@starship.com" , "company_id" : 1 , "exp" : 1742265057 } The fields above have the following purpose: external_system_email : String The email address of the user making this request. The authorization depends upon the permissions that are granted to this user in the system. company_id : Integer This is the company ID that uniquely identifies your company in the SkillsDB system. exp : Integer Expiry date in epoch format until which this JWT is valid. ​ Procedure For every request, the external client system needs to call every GraphQL query and mutation using the Authorization header in the following format: Name: Authorization Value: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 SkillsDB, based on the JWT and the user that corresponds to it, will proceed ahead with the request and perform the operation or return an error depending on the outcome. If you decide to rotate the key, SkillsDB will need to be provided with the new public key and the signature algorithm used. Otherwise your requests signed with the new private key will not work. ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## API Changelog URL: https://help.skillsdb.com/api-docs/changelog Quick Summary: Every change to the public REST API lands here with a date. Inside v1 every entry is additive — nothing here ever breaks an existing integration. ​ 2026-09-18 — Cold-start fixes from a greenfield customer simulation (pre-release) Still pre-release. A brand-new company driven only over the API could not reach four core loops. All fixed; three contract corrections ride along. Added The grading scale is writable. POST /grading-scale , PATCH /grading-scale/{id} , DELETE /grading-scale/{id} ( careers:write ). A new company has an empty scale, and every grading operation needs a gradeId , so no grade could be recorded before this. Grades lock once in use. Survey templates. GET|POST /survey-templates , GET /survey-templates/{id} ( surveys:read / surveys:write ). Create takes the questions; the response’s latestVersion.id is the templateVersionId for POST /surveys . accessLevel on bulk people records. POST /bulk/people takes the same accessLevel as POST /people ; a new person without it is basic , an existing person’s level changes only when it is sent. Career sections can be renamed. PATCH /careers/{id}/sections/{careerSectionId} takes name and description (they belong to the library section) alongside minimumRequiredSkills . Reorders take ids . The three career reorders accept { "ids": [...] } like every other reorder; levelIds , sectionIds and skillGroupIds stay as deprecated aliases. Skill-request decisions take reason . Same field as trainings and learning suggestions; notes stays as a deprecated alias. Fixed POST /org/countries returned 500 for every value. A company country is a link to the global country list; the name must now match GET /countries exactly, otherwise a 400 on name . Skills attached through a section never reached leveled assignees. They were not activated on the career’s levels; they now are, like skills attached directly. GET /careers/{id}/people returned every person in the company. It now lists the career’s holders only; an empty career is an empty list. An assessment start refused for a reason other than state said “state”. The 409’s detail now names the real obstacle (no audience, no flow, nothing to answer). Changed (pre-release corrections) An unresolvable person in a request field is a 400, not a 404. managerEmail , people[].email , emails and delegatedApproverEmail that name nobody in your company answer a validation problem with code unknown_person on the field. A path segment ( /people/{id} ) still answers 404. Both remain indistinguishable from another company’s person. PATCH /people-flags/{id} and PATCH /skill-flags/{id} are partial. name is no longer required on update. ​ 2026-09-10 — Error documents never leak internals (pre-release) Still pre-release. Three corrections to the problem document every error returns. Changed (pre-release corrections) The trial-expiry 403 explains itself. When a workspace’s trial has expired, detail now says so; it previously read “Forbidden Exception”. The error: "trial_expired" and upgrade_url members are unchanged and are now described in the specification. An unexpected 5xx never carries the server’s own text. Its detail is a generic explanation with the request id to quote to support. Database failures never reach detail . A write that breaks a uniqueness rule answers 409 with a fixed explanation instead of the database’s message, which named internal tables and values. Any other database failure is a generic 500 . See Errors . ​ 2026-09-10 — Org value delete deactivates (pre-release) Still pre-release. DELETE /org/{dimension}/{id} shipped as a permanent, confirm-guarded removal. The app has never removed an org value — deactivation is its only retirement path — and the API now matches it. The route, its 204 and its query parameter are unchanged, so no client breaks. Changed (pre-release corrections) DELETE /org/{dimension}/{id} deactivates instead of removing. It is the same operation as PATCH { "isActive": false } , with the app’s own side effects: the value leaves every person’s profile, draft surveys and draft assessments drop it, and the dimension’s history records who retired it (buildings only flip the flag, as in the app). The value stays readable with isActive: false and PATCH { "isActive": true } reactivates it. No 409 from this route any more. Nothing is destroyed, so there is nothing to confirm and nothing that can conflict. A held value deactivates on the first call; a value referenced by another org value deactivates too. ?confirm=true is deprecated and ignored. It is still accepted so existing calls keep working. Idempotent. Deleting an already-inactive value returns 204 . Retiring a state completes. Retiring a state — by either verb — returned 500 once the value had already left people’s profiles, because the state dimension was missing the storage its ten siblings have. Both verbs now finish the whole retirement: draft surveys and draft assessments drop the state, and the history records who retired it. Values that predate the active flag retire completely. A value old enough to have no stored active flag reads as active, and retiring one now runs the same cleanup as any other value on both DELETE and PATCH { "isActive": false } . Previously only the flag changed, leaving the value on people’s profiles and in draft surveys and assessments. See Org Structure . ​ 2026-09-07 — The remaining resource set (pre-release) Eight functional areas join the API, completing the planned v1 surface. Every scope that was previously refused as inert is now grantable and backed by endpoints. Added Certifications — the certification library and types ( Certification , Certification Type ), and people’s certification records with expiry and a guarded evidence download ( Person Certification ), on certifications:read / certifications:write . Assessments — assessment results and a queued nudge, on assessments:read / assessments:write ( Assessment ). Proficiency — grading reads and writes over person skills, on p --- ## Careers URL: https://help.skillsdb.com/api-docs/concepts/careers Quick Summary: A career is not a flat record — it is a complete competency model of levels, sections, skill groups, skills and learnings. This group is the model itself. Who holds a career is a career assignment in Team Data . ​ The resources Resource What it is Career The competency model: levels, sections, skill groups, skills and learnings Career type The families careers are grouped under, such as Job Role and Group Grading scale The single company-wide scale every benchmark and grade references ​ Read the whole model in one call The career object is the library entry. GET /api/v1/careers/{id}/definition returns the entire competency model — levels, sections, groups, skills and learnings — in a single response, which is what an integration rendering a career should use rather than walking the parts. ​ One scale, company-wide There is exactly one grading scale per company, and it is read-only over the API . Every benchmark on every career and every achieved grade references a rung of that scale by id. Grades and benchmarks are always returned as resolved rungs ( { id, grade, label } ), never as bare integers — an integer alone does not rank meaningfully. The scale locks once any grade is in use, which is why it is not writable here. ​ Deleting is guarded A career type cannot be deleted while careers still use it. This is the pattern across the library resources: definitions that other records point at refuse deletion rather than orphan those records. ​ Activity GET /api/v1/careers/{id}/activity is the fullest activity feed on the API — roughly 40 event types covering lifecycle, settings, skills, sections, levels, groups, learnings, assignments, labels and flags. It accepts from / to date filters, which makes it the feed a poller should watch. --- ## Certifications URL: https://help.skillsdb.com/api-docs/concepts/certifications Quick Summary: A certification is a library entry : a name, a description, the type it groups under, and the authority that issues it. What a person holds — their record, its approval workflow, evidence and expiry — is a person certification in Team Data . ​ The resources Resource What it is Certification type The families certifications group under, such as Regulatory and Vendor , in display order Certification The library entry: name, description, type and issuing authority ​ The distinction that matters Two resources sound alike and are not: Certification Person certification Answers ”What certifications exist?" "Who holds what, and until when?” Lives in System Objects — this group Team Data Carries Name, description, type, issuer Workflow state, dates, identifier, evidence, history An integration building a picker reads this group. An integration syncing compliance evidence writes person certifications. ​ Deleting is guarded A certification type still in use cannot be deleted without confirming. Each type carries how many certifications reference it, so you can check before you try. --- ## People & Organization URL: https://help.skillsdb.com/api-docs/concepts/people-and-organization Quick Summary: People are the anchor of the whole API — every record in Team Data names a person. This group covers the person record itself, the company-defined attributes a person references (job titles, people types, access levels, countries), and the eleven org dimensions plus the manager hierarchy. ​ The resources Resource What it is Person The workforce record: identity, contact details, access level, manager, org placement and lifecycle Org structure Eleven flat dimensions saying where someone sits , and the manager hierarchy saying who they report to ​ Addressing a person Every person-shaped path slot on this API takes the person’s email address — the primary, documented form — or the opaque id from any response. Request fields that reference a person are email fields ( managerEmail , delegatedApproverEmail , { "email": ... } ). Email is unique across all of SkillsDB, not just your company. The field an integration should key on is externalId — your own identifier, carried on the person record for exactly this purpose. ​ Attributes are their own library Job titles, people types, access levels and countries are company-configured lists, not free text on the person. A person references them; you manage the lists themselves through their own endpoints. Access levels are the one list you cannot extend — four are assignable ( basic , manager , admin , fullaccess ) and three are legacy and read-only. ​ Syncing a workforce POST /api/v1/bulk/people takes a batch of people in one call — the shape an HRIS sync needs. For a single dimension, PUT /people/{id}/org-schema/{dimension} replaces that dimension with exactly the supplied list, which is what makes a repeatable sync idempotent. SCIM and this API are alternatives, not layers. If your identity provider provisions people through SkillsDB’s SCIM integration, do not also sync people through this API against the same tenant. ​ What is not here What a person knows, holds or has done is Team Data — person skills, assessments, certifications, training and career assignments all live there. This group is only the person and where they sit. --- ## Skills URL: https://help.skillsdb.com/api-docs/concepts/skills Quick Summary: A skill is a company-level definition: a name, a description, and its usage across careers and people. What a person scores on a skill is a person skill in Team Data . What a skill is configured as on a career — its benchmark, Required status and per-level activation — belongs to the career . ​ The resources Resource What it is Skill The company-level definition: identity, description, usage, versions and activity Skill request The workflow by which someone asks for a skill to be added to the library ​ One definition, three places it is used A single skill definition is referenced from three directions, and keeping them distinct is the thing to get right: Where What it means Resource The library The definition itself — name, description, version history Skill On a career The benchmark, Required status and per-level activation for that career Career On a person The self and manager grades, benchmark and flags for that person Person skill Changing the library definition never rewrites a grade. Skills are versioned, and a training completed against an earlier version is identifiably stale rather than silently valid. ​ Adding to the library A skill request proposes a name and description. Approving it creates the skill and assigns it to the requester; rejecting it records the decision. Either way the decision is final — deciding a decided request returns a conflict . ​ Activity GET /api/v1/skills/{id}/activity is a version log , not a change feed — exactly three event types ( baseline , version_created , renew_training ). See the activity event envelope for the shared shape. --- ## Team Data URL: https://help.skillsdb.com/api-docs/concepts/team-data Quick Summary: Team Data is everything the API records about a person , as opposed to what the company configures. Every resource here has the same three-part shape — person + definition + evidence — and these are the records an integration syncs daily. ​ The shared shape Every Team Data record joins a person to a System Object and attaches what was observed: Part What it is Person Who the record is about — addressed by email address, or the opaque id Definition The system object it points at: a skill, a certification, a career, a learning item, a survey Evidence What was observed: grades, dates, status, files, notes, approval decisions and history Once you know a resource’s definition side, you already know most of its read shape. The differences are in the evidence. ​ The resources Group Resource The definition it points at Proficiency Data Person skill Skill Assessment Results Assessment Skills, within a cycle Certification Data Person certification Certification Training Data Learning plan Learning item Training Data Training record A person skill Survey Results Survey , Survey response A survey template version Career Assignments Career assignment Career ​ Three rules that hold across the group Grades are resolved rungs, never integers. Every grade and benchmark is returned as { id, grade, label } against the company grading scale . A bare integer does not rank. Expiry is derived from a date, never from a status. An approved certification or training stays approved in storage after its date passes. Reads carry a separate expiry signal — use it, rather than inferring currency from the status. History is written, not overwritten. Unassigning a career records career history first. Renewing a training supersedes the old record rather than deleting it. Removing a person skill writes history before it goes. Past state stays readable. ​ The definition must exist first Team Data records cannot invent their definition side. A training record requires the skill to already be on the person’s profile. A learning plan requires the catalogue item. A person certification requires the library certification. Sync the System Objects first, then the records about people. ​ Detecting change There are no webhooks. Poll the activity feeds — see Polling for Changes for the pattern, and the activity event envelope for the shape. --- ## Training Library URL: https://help.skillsdb.com/api-docs/concepts/training-library Quick Summary: The training library is your company’s catalogue: courses, videos, documents and sessions, each described by five company-defined reference lists. Assigning an item to a person creates a learning plan in Team Data — the catalogue and the assignment are different resources. ​ The resources Resource What it is Learning item A catalogue entry — the course, video, document or session Learning reference list The five lists describing an item: learning type, provider, format, audience, course level Learning suggestion A proposed catalogue entry, pending a global administrator’s decision ​ Five lists, one path A learning item points at up to five reference entries. All five lists are served under a single parameterised path, /api/v1/learning-reference/{list} , with the same shape and the same operations — learn one, and you have learned all five. Each list is company-defined and ordered, and deleting an entry that is in use is guarded. ​ Suggestions become items Anyone who can see the training library may submit a suggestion . The submitter or a global administrator may revise it while it is pending; only a global administrator approves or rejects it. On approval the suggestion becomes a learning item with the same id . A pending or rejected suggestion is never a catalogue item — do not treat a suggestion id as an item id until it is approved. ​ Two different records of “what someone has done” Assigning from this library produces a learning plan . That is a different resource from a training record , which hangs off a person skill . They share no shape and are never interchangeable — both live in Training Data . --- ## conflict URL: https://help.skillsdb.com/api-docs/errors/conflict Quick Summary: The request is well-formed but the current state of the resource refuses it — most often a guarded delete . The body extension members tell you exactly what stands in the way. ​ What happened Common cases: Deleting a career that still has sections, skills, levels or assigned people. The body carries confirmRequired: true and a dependencies object with the counts. Retrying with ?confirm=true performs the delete anyway. Deleting a career level where people are assigned at that level. The body carries wouldUnassignPeopleCount — deleting unassigns those people from the entire career . Retry with ?confirm=true to proceed. Deleting a career type that careers still use. A concurrent request with the same Idempotency-Key is still executing — retry shortly to receive its stored response. ​ What to do Read the extension members, decide deliberately, and — for guarded deletes — retry with ?confirm=true only when the reported consequences are acceptable. --- ## idempotency-key-reused URL: https://help.skillsdb.com/api-docs/errors/idempotency-key-reused Quick Summary: This Idempotency-Key was already used for a request with different method, path or body. Keys identify one exact request; use a fresh key for new content. ​ What happened Within a key 24-hour lifetime, resending the same key with the same content replays the stored response (with Idempotency-Replayed: true ). Sending the same key with different content is always an error — otherwise a retry could silently perform the wrong operation. ​ Likely causes Reusing one constant key for many different requests. Building the key from something that does not change with the payload. ​ What to do Generate a unique key (a UUID is ideal) per logical operation, reuse it only for retries of that exact request, and never share keys across different payloads. --- ## Error Catalogue URL: https://help.skillsdb.com/api-docs/errors Quick Summary: Every REST API error is an RFC 9457 problem+json body. Its type field is a URL that resolves to a page in this catalogue telling you what happened and what to do. Every error response has Content-Type: application/problem+json and this shape: { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be at most 200" , "instance" : "/api/v1/careers" , "requestId" : "01a01ed7-a41b-7183-a017-be375fd23874" , "errors" : [{ "field" : "limit" , "code" : "out_of_range" , "message" : "..." }] } Always log the requestId — it is the one string SkillsDB support can trace a request by. Some errors carry extra fields (extension members), documented on their pages. Type Status When validation-error 400 The request itself is malformed invalid-credential 401 The API key is missing, wrong, expired or revoked insufficient-scope 403 The key does not hold the scope the operation requires — grant it insufficient-permissions 403 The acting person is not allowed to do this — rebind the key, scopes will not help not-found 404 No such resource in your company method-not-allowed 405 The path exists, but not for this HTTP method conflict 409 The current state of the resource refuses the request idempotency-key-reused 409 Same Idempotency-Key, different content version-gone 410 The API version was sunset unprocessable 422 Well-formed, but rejected by a business rule rate-limit-exceeded 429 Over the hourly allowance internal-error 500 Our fault — quote the requestId to support --- ## insufficient-permissions URL: https://help.skillsdb.com/api-docs/errors/insufficient-permissions Quick Summary: The key authenticated and holds the right scope, but the acting person — the SkillsDB user the key acts as — does not have permission for this operation. Editing the key’s scopes will not help; bind the key to a person who can do this in the app. ​ What happened Every operation requires two things: the key must hold a scope (like careers:write ) and the person the key acts as must hold the matching permission in SkillsDB. The effective permission is always the intersection — a key can never do more than its acting person could do in the app. This error is the second half of that rule. Typical causes: The acting person’s access level cannot perform the operation at all (for example, a Basic employee listing people). The operation targets someone outside the acting person’s span of control (a manager-bound key reading a person who does not report to them — though where a resource exists in another company this is a 404 , never a 403 ). The acting person’s role forbids the specific write (for example, granting an access level above their own). ​ What to do Bind the credential to a person with the right access level — an administrator does this under Settings → API Credentials — or adjust that person’s role in SkillsDB. Do not grant more scopes: a key whose acting person is denied is denied regardless of scopes. ​ How this differs from insufficient-scope insufficient-scope insufficient-permissions Who refused The key’s scope gate The acting person’s permissions detail names the missing scope ( 'people:read' ) the operation or access level Fix grant the scope rebind the key / change the role Branch on type , not on detail — the two remedies are opposites. --- ## insufficient-scope URL: https://help.skillsdb.com/api-docs/errors/insufficient-scope Quick Summary: The key authenticated, but it was not granted the scope this operation requires. detail names the missing scope. Fix: an administrator grants it under Settings → API Credentials — it takes effect on the very next call. ​ What happened Every operation declares the scope it requires (shown as Requires scope on its reference page). This key’s scope list does not include it. The request was refused at the scope gate — before any data was read or any permission of the acting person was evaluated. ​ What to do Grant the named scope to the key. Note that :write never implies :read — grant both if you need both. Nothing about the acting person needs to change for this error. ​ Not the same as insufficient-permissions If the key does hold the scope but the person it acts as is not allowed to perform the operation, you get insufficient-permissions instead — and granting scopes will not fix that one. The two are separate problem types precisely so your error handling can branch on type rather than parse detail . --- ## internal-error URL: https://help.skillsdb.com/api-docs/errors/internal-error Quick Summary: Something failed on our side. The response deliberately contains no internals — the requestId is the handle our engineers trace it by. ​ What happened An unexpected error occurred while serving the request. It has already been reported to our monitoring with the same requestId your response carries. ​ What to do Retry once with backoff — many 500s are transient. If it persists, contact support quoting the requestId and the time of the request. For write requests, retry with the same Idempotency-Key you sent originally — that guarantees the operation cannot be performed twice. --- ## invalid-credential URL: https://help.skillsdb.com/api-docs/errors/invalid-credential Quick Summary: The request did not carry a usable API key. The response is deliberately generic — it never says whether a key exists, expired, or was revoked. ​ What happened Authentication failed. Every /api/v1 request must carry Authorization: Bearer sdb_live_... with a live key. ​ Likely causes The Authorization header is missing, or not in Bearer form. The key was revoked, or its rotation grace window has ended. The key has passed its expiry date. A different kind of token (a session token, a JWT) was sent — the public API accepts only API keys. The acting person bound to the key was deactivated or moved companies. ​ What to do Verify the header format first. If it is correct, ask a company administrator to check the key under Settings → API Credentials — and to rotate or issue a new key if needed. Keys are shown once at creation; a lost key cannot be recovered, only replaced. --- ## method-not-allowed URL: https://help.skillsdb.com/api-docs/errors/method-not-allowed Quick Summary: The URL is right but the verb is wrong. The detail and the allowedMethods extension list the methods this path does support. ​ What happened You called an existing endpoint with an HTTP method it doesn’t implement — for example DELETE /api/v1/ping , which only answers GET . This is distinct from not-found : a 404 means no such path, a 405 means the path exists and you should change the method, not the URL. ​ Example { "type" : "https://help.skillsdb.com/api-docs/errors/method-not-allowed" , "title" : "Method not allowed" , "status" : 405 , "detail" : "DELETE is not supported at /api/v1/ping. Allowed: GET, HEAD." , "instance" : "/api/v1/ping" , "requestId" : "01a05ac5-…" , "allowedMethods" : [ "GET" , "HEAD" ] } ​ What to do Switch to one of the methods in allowedMethods . If you expected this operation to exist — say, a DELETE on a resource that only documents POST — check the endpoint’s page in the API reference for the supported operations and any alternative (many removals are modelled as dedicated sub-resources or deactivate endpoints). --- ## not-found URL: https://help.skillsdb.com/api-docs/errors/not-found Quick Summary: The id does not exist in your company . The API never distinguishes “does not exist” from “exists in another company” — both are 404. ​ What happened The resource id in the URL (or referenced in the body) resolved to nothing your key is entitled to see. ​ Likely causes The resource was deleted. The id was copied from another environment or another company. A sub-resource id (a level, section, or skill id) belongs to a different career than the one in the URL. ​ What to do Re-list the parent collection to obtain current ids. Treat ids as opaque strings and never construct them. --- ## rate-limit-exceeded URL: https://help.skillsdb.com/api-docs/errors/rate-limit-exceeded Quick Summary: The key exceeded its hourly allowance for this request class. Wait for the window to reset — the Retry-After header says how many seconds. ​ What happened Every response carries the current window state in headers: Header Meaning RateLimit-Limit The allowance for this request bucket RateLimit-Remaining Requests left in the current hour window RateLimit-Reset Seconds until the window resets Requests are counted per key in three buckets — reads (GET), writes (POST/PUT/PATCH/DELETE) and bulk operations. See rate limits for the numbers. ​ What to do Back off until Retry-After elapses, then resume. Well-behaved integrations watch RateLimit-Remaining and slow down before hitting zero. If your integration legitimately needs more, ask your SkillsDB contact about a per-key allowance. --- ## unprocessable URL: https://help.skillsdb.com/api-docs/errors/unprocessable Quick Summary: The request was understood but violates a SkillsDB rule. The detail states the rule; change what you are asking for, not just the syntax. ​ What happened Unlike a 400, everything about the request was syntactically valid — the combination is what gets rejected. ​ Known rules Assessments require proficiency grading : enabling a career assessments setting while proficiencyGrading is disabled is rejected rather than silently accepted. Career library management disabled : authoring careers over the API requires the same company module setting the app enforces. ​ What to do Read the detail , change the request to satisfy the rule (for example enable proficiency grading in the same PATCH), or ask an administrator about the relevant company setting. --- ## validation-error URL: https://help.skillsdb.com/api-docs/errors/validation-error Quick Summary: The request could not be accepted as written — a parameter is out of range, a field is unknown, or a value has the wrong shape. Fix the request; retrying unchanged will fail again. ​ What happened The API rejected the request before doing any work. The errors array names each offending field with a machine-readable code . ​ Likely causes limit above 200 or offset above 10,000 — the API rejects these rather than silently clamping. A filter or sort field that is not on the endpoint whitelist ( not_filterable / not_sortable ). An unknown body or query member — including any attempt to pass companyId ; tenancy always comes from your key. A malformed id ( invalid_id ), or an Idempotency-Key header over 200 characters. ​ What to do Read the errors array, fix each named field, and resend. Do not build retry loops around 400s — the same request always produces the same 400. --- ## version-gone URL: https://help.skillsdb.com/api-docs/errors/version-gone Quick Summary: This API version has passed its published sunset date and no longer serves requests. The detail links the migration guide. ​ What happened Versions are deprecated with notice long before being removed (see the versioning policy ). During the deprecation window every response carries Deprecation , Sunset and Link headers announcing the date — after that date, every route of the version answers 410. ​ What to do Follow the migration guide linked in detail , move to the current version base path, and watch for Deprecation headers in your integration logs so the next sunset never surprises you. --- ## Filtering URL: https://help.skillsdb.com/api-docs/filtering Quick Summary: Use the where parameter in SkillsDB GraphQL queries to filter results by field values, with support for operators like _eq , _like , _in , and more. The queries that support pagination will also provide the facility of filtering out the results. This is helpful in narrowing down the result set based in your preferences. In such queries, we provide the an input parameter called where , which will mostly be inside the input parameter or in some cases will b the top level parameter. Let’s see an example: query getDomains { getDomains ( input : { where : { DomainName : { _like : "%Vercel%" } } }) { count data { DomainId DomainName } } } Here you see the where input parameter in action inside the input parameter. Notice the parameter called _eq . This means that the SkillName should be equal to the given value. On the lowest level - that is, the leaf node of an object which is a primitive type - we provide the following operations for comparison: _eq : String . Equal to the provided value _gt : String . Greater than the provided value _gte : String . Greater than or equal to the provided value _in : [String!] . Resulting value must be one of the provided values _is_null : Boolean . Resulting value must be null _like : String . Resulting value must be like the provided value, not requiring that it is an exact match. The value for this operator must be provided as '%value%' , '%value' or 'value%' . _lt : String . Less than the provided value. _lte : String . Less than or equal to the provided value. _neq : String . Not equal to the provided value. _nin : [String!] . Result should not be within the provided input array. _nlike : String . Negation of the like operator mentioned above. ​ Multiple values to compare using where parameter Inside the where parameter and the value it is currently focusing on, you will see that the where clause can be applied on multiple fields in the result set. Taking the example from the above example: query getDomains { getDomains ( input : { where : { DomainId : { _eq : 10 } DomainName : { _like : "%Vercel%" } } }) { count data { DomainId DomainName } } } Notice that we now have the DomainId in the picture as well. ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Getting Started URL: https://help.skillsdb.com/api-docs/getting-started Quick Summary: SkillsDB exposes a public GraphQL API that your internal systems can use to integrate with and automate processes. Contact SkillsDB to whitelist your domain before beginning. SkillsDB exposes a public GraphQL API. This API can be used by your internal systems to communicate with SkillsDB and automate processes seamlessly. We use this same API internally for developing our application. The next section describes the authentication modes we support and how to communicate with the API. Please contact us before beginning, as your API endpoint URL is required to be whitelisted. SkillsDB limits connections to allowed domain URLs only. API interactions are limited a single authenticated SkillsDB account only. ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Our Commitment to GraphQL Integrators URL: https://help.skillsdb.com/api-docs/graphql-commitment Quick Summary: If you are integrated with the SkillsDB GraphQL API today, nothing changes for you. The REST API is an addition, not a replacement, and you are not being asked to migrate. ​ The position, plainly SkillsDB now offers two integration surfaces: this GraphQL API and a REST API with API-key authentication. The REST API exists because some customers asked for API keys and a conventional REST shape — not because GraphQL is going away. No migration is required or planned. Your existing GraphQL integration continues to work, on the same endpoint, with the same authentication. No deprecation clock is running. If that ever changes, you will hear it from us directly and in writing, with a generous timeline — not by discovering a notice in a changelog. The GraphQL API continues to be maintained. It is the same API our own application runs on, so it receives the same operational attention as the product itself. ​ What has actually changed for GraphQL integrators Two improvements, both in your favour: Schema introspection is now available to authenticated callers. Previously the schema was not readable outside our own environments; now any authenticated request can run introspection — enabling schema discovery, client code generation, GraphQL IDE tooling, and visibility of @deprecated markers, which are GraphQL’s in-band signal that a field is scheduled to change. Anonymous callers still cannot introspect. A breaking-change gate now guards the schema in CI. A change that would remove or narrow anything you use cannot merge without an explicit, ticketed approval — the schema can no longer change out from under you as a side effect of a refactor. ​ Choosing between the APIs Use whichever fits. The REST API may suit new server-to-server integrations that prefer API keys, fixed resource shapes, and a published OpenAPI specification; GraphQL remains the right choice when you want to shape responses precisely. Both run against the same underlying system and the same permission model. Nothing about using one forecloses the other. --- ## GraphQL Schema URL: https://help.skillsdb.com/api-docs/graphql-schema Quick Summary: The full SkillsDB GraphQL schema documentation is available online. You must be logged in as a SkillsDB user to access it. Here is a link to our GraphQL Schema. Note that you must be logged in as a user of SkillsDB in order to access schema documentation. ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Learning Resource Assignment URL: https://help.skillsdb.com/api-docs/learning-resource-assignment Quick Summary: This tutorial covers the GraphQL operations for viewing, assigning, and updating learning resources (IDPs) for people in your SkillsDB company, including migration paths from the legacy API. ​ Get/List People Learnings (IDP) On the legacy API access the used to an API which list all learnings (IDPs) which are assigned to peoples. The below API: GET - {{baseURI}}/IDP/{{companyID}}?part={{part}} On the new GraphQL API use the below query to list/get people learnings (IDPs) query GetAllPeopleLearningSummary { getAllPeopleLearningSummary ( input : { limit : 20 , offset : 0 , where : { emailAddress : { _like : "" } } } ) { count data { PersonId FirstName LastName EmployeeId MgrPersonId MgrFirstName MgrLastName MgrEmailAddress LearningId ReferenceId # LearningPlanActivityIDOutsideSystem on the legacy API LearningTitle Status PercentComplete # LearningPlanPercentComplete on the legacy API DateStarted # LearningPlanStartDate on the legacy API DateCompleted # LearningPlanEndDate on the legacy API } } } ​ Get/List Learnings(IDPs) for Person with Email Address On the legacy API there used to be an API to get learnings/IDPs for specific person by Email Address. On the new GraphQL API we’ll use the above getAllPeopleLearningSummary query by using email filter as below, for more on filtering please check out Filtering documentation. where : { emailAddress : { _eq : "email@domain.com" } ​ Create and Assign Learning to a Person On the legacy API there used to be an API to create IDP record and assign to a person at the same time. Which is: POST- {{baseURI}}/CreateIDPRecord/{{companyID}} with the below payload: { // Learning plan (course) outside Id used in other system (if there is), So it can be referenced. OPTIONAL, But good to have field. "LearningPlanActivityIDOutsideSystem":"SDB62540021", // Person email address to assign or update the learning plan current status. REQUIRED "EmailAddress": "tadesse@skillsdb.com", // Short Title for the learning plan, if this learning plan doesn't exists in the system, it will be created. REQUIRED "LearningPlanTitle": "NEST AND GRAPHQL INTEGRATION", // Long description of the learning plan, OPTIONAL "LearningPlanDescription":"Programming", // The duration that will take to complete this course. OPTIONAL "LearningPlanDurationHours":10, // A url in which the learning plan (course) could be redirected. OPTIONAL "LearningPlanURL":"https://www.sampleurl.com/pathtothecourse", // A unique Id of learning plan types which is generated by skillsdb system, you can get those ids from SkillDb web app. If you don't want to use Id you can use learning plan type Name. OPTIONAL "LearningPlanTypeId": 15, // This is a learning plan type name in which the system will take the Id based on this name. New learning plan type will be created if there is no learning plan type with the given name. Please make sure you are using the exact names of existing learning plan types (to avoid unneccesary duplicates). OPTIONAL "LearningPlanTypeName":"Sample Learning Plan Type", // Percentage representation of the course(learning plan) completion. OPTIONAL, but Reuired if you want to score with this API. "LearningPlanPercentComplete": 100, // The time when this course(learning Plan) started by an employee.The Date Format shuld be (dd.MM.yyyy). OPTIONAL "LearningPlanStartDate": "15.06.2023", // The time when this course(learning plan) gets completed by an employee. The Date Format shuld be (dd.MM.yyyy). OPTIONAL "LearningPlanEndDate": "30.12.2023" } On the new GraphQL API we’ll use the below mutation to create and assign learning/IDP to a person using email address: mutation AddAndAssignlearningComposite { addAndAssignlearningComposite ( input : { EmailAddress : "tadesse@skillsdb.com" Title : "NeW Updated Learning" # title of the learning plan Description : null # any description DurationInHours : 12 # leaning plan duration (master data level) when this learning gets assigned to other person, this duration will be used OverrideDurationHours : 23 # this will override the above learning plan duration for this person PercentageCompleted : 50 # percentage completed StartDate : "2025-01-15" # start date of the learning EndDate : "2025-06-20" # percentage should be 100% to log this ReferenceId : "LNOPS-11222" # reference Id to other system (for your reference) LearningPlanActivityIDOutsideSystem equivalent from legacy system LearningPlanURL : "htts://learn.domain.com/lnops-11222" # url of the learning plan } ) { success message rowsAffected } } ​ Update Person learning (IDP) On the legacy API there used to be an update API for persons learning plan (IDP). Which is: POST - {{baseURI}}/skills/{{companyID}} with the below json { "LearningPlanActivityIDOutsideSystem" : "SDB62540021" , "EmailAddress" : "emial@domain.com" , "LearningPlanPercentComplete" : "85" , "LearningPlanStartDate" : "15.06.2023" , "LearningPlanEndDate" : "15.06.2023" } On the new GraphQL API we’ll use the above addAndAssignlearningComposite mutation with the below payload: mutation AddAndAssignlearningComposite { addAndAssignlearningComposite( input: { EmailAddress: "email@domain.com" ReferenceId: "LNOPS-11222" # reference Id to other system (for your reference) LearningPlanActivityIDOutsideSystem equivalent from legacy system PercentageCompleted: 100 # percentage completed StartDate: "2025-01-15" # start date of the learning EndDate: "2025-06-20" # percentage should be 100% to log this } ) { success message rowsAffected } } ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Migrating from Legacy API URL: https://help.skillsdb.com/api-docs/migrating-from-legacy-api Quick Summary: The legacy REST API was deprecated in 2025. This guide outlines the key differences in access, authentication, and response format to help you plan your migration to the new GraphQL API. SkillsDB has shifted from the legacy platform, which was deprecated in 2025. If you using the legacy API, please refer to the points below in your planning migration to the new GraphQL API. This document outlines the key differences between the legacy REST API and the new GraphQL API for SkillsDB, highlighting usage, consumption patterns, and access endpoints to assist developers during migration. Access - Base URL REST API (Legacy) : https://***api.azurewebsites.net/Service1.svc GraphQL API (New) : The Production and Staging URLs of our GraphQL APIs can be found on our GraphQL schema page . You need to be a user on the SkillsDB app to view the docs. Request Format REST API (Legacy) : Multiple HTTP endpoints per resource GraphQL API (New) : Single endpoint with flexible queries / mutations Authentication REST API (Legacy) : Token via POST /login using APICode GraphQL API (New): JWT signed by client, Validated with public key Response REST API (Legacy) : Fixed shape per endpoint GraphQL API (New): Client-defined structure ​ Authentication/Authorization: On the legacy API access there used to be a login to obtain bearer access token, which is: POST - {baseURI}/login with payload of :- { /// Get this API Key from your company skills db portal (Only Administrator can get this information.) "APICode" : "{{API_Key}}" } On the new GraphQL APIs you will be managing/signing JWT token with your private key and provide us the public key to validate the JWT. For more details please look into this Authentication documentation. ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Pagination URL: https://help.skillsdb.com/api-docs/pagination Quick Summary: SkillsDB GraphQL queries support pagination via limit and offset parameters, available either inside the input object or as top-level parameters depending on the query. We provide the option of pagination in queries. You will find it in two different input formats, both of which eventually provide limit and offset parameters. ​ Parameters inside input object Mostly, you will see the limit and offset inside the input object. For example: query getJobRoles { getJobRoles ( input : { offset : 0 , limit : 100 }) { count data { JobRoleId JobRole } } } ​ Directly as Parameters For such queries, you will find that the limit and offset parameters are the top level parameters in the input. For example: query getAllPeople { getAllPeople ( offset : 0 , limit : 100 ) { count data { PersonID FirstName LastName EmailAddress Active CompanyID GroupId } } } ​ Total Count In the result set of all the queries, you will find 2 top level fields: count - provides with the total number of records for the requested data data - array of objects that containing the actual returned data ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## People Provisioning URL: https://help.skillsdb.com/api-docs/people-provisioning Quick Summary: This tutorial covers the GraphQL operations for creating, updating, and viewing people in your SkillsDB company, including migration paths from the legacy API. ​ Get List of People On the legacy API access the below API were used to retrieve list of employee/people details. GET - {{baseURI}}/Personnel/Get/{{companyID}}?part={{part}} On the new GraphQL API the below query will be used to retrieve/list all people. Please refer to Filtering and Sorting documentations for more details about filtering and sorting. query GetAllPeople { getAllPeople ( limit : 10 offset : 0 orderBy : { FirstName : ASC , LastName : ASC , EmailAddress : DESC } where : { EmailAddress : { _like : "" } } ) { count data { PersonID LastName FirstName EmailAddress GroupId NextAvailDate Gender Company BusinessPhone HomePhone MobilePhone FaxNumber Address City StateProvince ZipPostalCode PeopleCountries { CompanyCountry { Id Name } } WebPage Notes PeopleBusinessRegions { CompanyBusinessRegion { BusinessRegionId BusinessRegion } } PeopleDepartments { Department { DepartmentId DepartmentName } } JobTitle { JobTitleId JobTitle } PeopleType { PeopleTypeId PeopleTypeName } Manager { PersonID FirstName LastName EmailAddress } Active PeopleJobRoles { JobRole { JobRoleId JobRole JobRoleLevels { JobRoleLevelId Title SortOrder } } } } } } ​ Get Person/Employee by Email The legacy API uses the below API to retrive GET - {{baseURI}}/Personnel/Get/Email/{{companyID}}?email={{email}}&part={{part}} On the new GraphQL API we’ll use the above query: getAllPeople with the filter as follow: where : { EmailAddress : { _eq : "email@domain.com" } } ​ Filter People created by specific user On the new GraphQL API we’ll use the above query: getAllPeople with the filter as following: where : { CreatedByPersonId : { _eq : 4 } } ​ To get the person Id of the current session user, use the below query with the JWT auth header: query me { me { PersonID FirstName LastName EmailAddress Active GroupId } } ​ Add or Update People/Employees On the legacy API the below API have been used to add or update a person profile: POST - {{baseURI}}/Personnel/Insert/{{companyID}} On the new GraphQL API we’ll use the below Mutations to insert and update an employee/person. Insert a new person: mutation addPersonCompotsite { addPersonComposite ( input : { FirstName : "First Name" LastName : "Last Name" EmailAddress : "email@domain.com" # unique email address that is not added to our system SecurityGroup : GLOBAL_ADMIN # GLOBAL_ADMIN / MANAGER / EMPLOYEE YourPersonId : "Way-1234" # your system user id for the person Active : true ThirdPartyCompany : "Third Party Foundation" BusinessPhone : "101 101 101" MobilePhone : "202 202 202" HomePhone : "303 303 303" Address : "1 Wayne Street" Gender : Male # Male/Female FaxNumber : "404 404 404" Notes : "Notes on" StateProvince : "Gotham Province" WebPage : "https://wayne.com" ZipPostalCode : "46000" JobTitleName : "CTO" # define person's job title name (will be created if not exists) PeopleTypeName : "Technical" # define the person type name (this will be created if not exists) ManagersEmail : "manager@domain.com" # manager email address (the manager should be already added to our system) JobRoleNames : [ "Deployments" , "Software Development" ] # JobRole. Specify multiple Job Roles to be assigned to a person. OrgSchema : { Countries : [ "USA" , "UK" , "Finland" ] # country_name. Specify multiple Countries to be attached to this user BusinessRegions : [ "Los Gatos" ] # BusinessRegion - specify multiple business regions Departments : [ "Engineering" ] # DepartmentName. Specify Multiple Departments. } } ) { id success message } } CAUTION: This mutation will send welcome emails to users on production. Update Existing Person To update a person the below mutation can be used. Before that we need get Job Titles and/or People Types to get our system Ids if those are being updated: To get Job Titles use the below query: query getJobTitles { getJobTitles { JobTitleId JobTitle } } To get all of the People Types in your company use the below query query getPeopleTypes { getPeopleTypes { PeopleTypeId PeopleTypeName CompanyID } } Finally update person using the below mutation: mutation EditPerson { editPerson ( input : { PersonId : 123 # get from getAllPeople query LastName : "Last Name" FirstName : "First Name" YourPersonId : "1123654" SecurityGroupId : 7 # 7 for GlobalAdmin, 4 for Manager, 1 for Employee Gender : Male # Male/Female Company : "SDB" BusinessPhone : "444 4444 44" HomePhone : "4444 444 4444" MobilePhone : "+44444444444" FaxNumber : "45454545" Address : "Sample Address" City : "Sample city" StateProvince : "State province test" ZipPostalCode : "45454545" WebPage : "www.user.com" Notes : "This is a note." JobTitleId : 13 # get from getJobTitles query PeopleTypeId : 24 # get from getPeopleTypes ManagerEmailAddress : "tadesse@skillsdb.com" Active : false # activate or inactivate person AvoidUnassignmentForEmptyValues : true , # This flag determine to not unassign title, people type, manager when they have empty value } ) { success message rowsAffected } } Provide the AvoidUnassignmentForEmptyValues = true so that the Manager, Job Title and People Type attributes do not get assigned null. If this field is not provided or is false, then these 3 attributes will be assigned null. Always provide this value as true in every editPerson request unless you want to unassign/set null. Notice on the editPerson payload there is no org schema definition (i.e. department, country, business regions. To assign and/or unassign org schemas please the below query and mutation to get org schemas and assign/unassign from person Get list of org schemas : query GetCompanyOrgSchema { getCompanyOrgSchema { BusinessRegions { BusinessRegionId BusinessRegion } CompanyCountries { Id Name } Departments { DepartmentId DepartmentName } } } Assign/attach org schemas to person: mutation AttachOrgSchemaToPeople { attachOrgSchemaToPeople ( input : --- ## The Activity Event object URL: https://help.skillsdb.com/api-docs/resources/activity-event Quick Summary: SkillsDB keeps three append-only activity logs. All three share one envelope — what happened, when, who did it, what it relates to — with documented per-scope extras. Activity endpoints live with the object they describe; this page defines the shape, filters and pagination they all share. ​ The envelope Every activity event, on every scope, carries: Field Type Description id string Opaque entry id event string | null Event type, lowercase snake description string | null Human-readable summary performedById string | null Person who performed the change — null when the change did not originate from a person in SkillsDB performedAt string | null When it happened (UTC) ​ The three scopes Scope Endpoint Scope required Event types Extras Career GET /api/v1/careers/{id}/activity careers:read ~40 — lifecycle, settings, skills, sections, levels, groups, learnings, assignments, labels, flags emailSent , relatedPersonId , relatedSkillId , relatedSectionId , relatedLevelId , bulkGroupId Skill GET /api/v1/skills/{id}/activity skills:read exactly 3 — baseline , version_created , renew_training . A version log, not a change feed versionId , affectedUserCount , renewalOption Identity provider GET /api/v1/identity-provider-events people:read 13 — group lifecycle, user provisioning, permission changes, career assignment, membership oldValue , newValue , payloadSummary , source , externalMemberId , relatedPersonId , relatedPersonName , relatedGroupId , relatedGroupName The identity-provider scope is the only one recording changes SkillsDB did not originate — which is exactly what to check when data appears to change by itself — and the only one carrying before-and-after values. Its performedById is always null : the performer is the identity provider. It is also company-scoped rather than per-object, since provisioning events concern the whole tenant. ​ Shared filters All three scopes take the same filter set — event , from , to , performedBy , relatedPersonId — with the standard pagination ( limit up to 200, offset up to 10,000). A filter a scope cannot support is rejected with a validation error , never silently ignored: The skill log records no related person → relatedPersonId is rejected there. Identity-provider events have no SkillsDB performer → performedBy is rejected there. The career log supports the full set, plus bulkGroupId to group the rows of one bulk operation. An unknown event value is likewise a validation error rather than an empty page, so a typo never reads as “no activity”. ​ What is deliberately not here A company-wide change feed. Career and skill logs are scoped to one object; polling per object plus the identity-provider stream is the nearest v1 offers. The shared envelope is what makes a tenant-wide feed a later filter change rather than a new contract. Import runs. An import is a job with a status and a result, not an event — it does not fit this envelope and is deferred from v1. Row-level history tables. Internal audit exhaust, not an integration surface. --- ## The Assessment object URL: https://help.skillsdb.com/api-docs/resources/assessment Quick Summary: An assessment is a cycle with two independent tracks — employees self-assess and managers assess — each with its own window, deadline and status. Grades are captured inside the cycle and only later promoted into the person’s live skill record. Administer the cycle, read who participates and what they were graded, and pull the reports. Conducting an assessment — grading, and marking a track complete — is done in the product, not through the API. ​ Attributes Field Type Description id string Opaque assessment id title / description string status string | null Cycle lifecycle: draft , active , completed , cancelled tracks.employee / tracks.manager object { status, startedAt, endedAt, deadlineAt } per track — the same lifecycle vocabulary, kept separate. A cycle can be closed for employees and open for managers startedAt / endedAt / deadlineAt string | null Overall dates managerGradesVisibleAt string | null When the employee may see their manager’s grades: immediately , after_employee_assessment , after_manager_assessment , after_assessment_ended allPeople boolean Targets everyone rather than a scoped population counts object assigned , completed , employeesAssigned , employeesCompleted , managersAssigned , managersCompleted — over assessable people (those with a career that has proficiency and assessments enabled) createdAt / updatedAt string | null The detail read adds scope : { allPeople, businessUnitIds, divisionIds, countryIds, businessRegionIds, cityIds, siteIds, departmentIds, teamIds, shiftIds, peopleTypeIds } . Assessment scoping supports nine of the eleven org dimensions — building and state are not part of it. { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "active" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "draft" , "startedAt" : null , "endedAt" : null , "deadlineAt" : "2026-04-15T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "after_employee_assessment" , "allPeople" : false , "counts" : { "assigned" : 120 , "completed" : 0 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 0 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null } ​ Operations ​ Cycles Operation Method and path Requires scope List assessments GET /api/v1/assessments assessments:read Get an assessment GET /api/v1/assessments/{id} assessments:read Create an assessment POST /api/v1/assessments assessments:write Update an assessment PATCH /api/v1/assessments/{id} assessments:write Start a track POST /api/v1/assessments/{id}/start assessments:write End a track POST /api/v1/assessments/{id}/end assessments:write Attach population selections POST /api/v1/assessments/{id}/scope assessments:write Detach population selections DELETE /api/v1/assessments/{id}/scope assessments:write Nudge participants POST /api/v1/assessments/{id}/nudge assessments:write Active counts for the acting person GET /api/v1/assessments/active-counts assessments:read Creating takes title , description , managerGradesVisibleAt , the population — allPeople: true , or a scope of org dimension ids and optional peopleTypeIds — and the two deadlines ( employeeDeadlineAt , managerDeadlineAt ). A new cycle is draft on both tracks and its participants are enrolled immediately. Updating follows the cycle’s rules: title, description, visibility and population only while both tracks are draft; a track’s deadline only while that track is draft. Anything else is a 409 . Start and end take { "track": "employee" | "manager" } ( suppressEmails: true on start skips the start emails). Draft → active → completed, per track; the cycle becomes active when the first track starts and completed when both have ended — at which point manager grades held for after_assessment_ended are promoted into the live records. A track in the wrong state is a 409. A start refused for another reason — nobody would receive it, the self-assessment flow has not been configured, or the build has no step anyone can answer — is also a 409, and its detail names that reason. Scope attach/detach take the same nine id lists and apply only to a draft cycle that does not target everyone; attaching to an all-people cycle is a 409. Nudge takes { "target": "employee" | "manager" | "direct_reports" } and answers 202 — reminders are queued and delivered asynchronously. direct_reports is relative to the acting person as a manager. ​ Participation Operation Method and path Requires scope List people in an assessment GET /api/v1/assessments/{id}/people assessments:read List exclusions GET /api/v1/assessments/{id}/exclusions assessments:read Get a person’s participation GET /api/v1/assessments/{id}/people/{personId} assessments:read Exclude or re-include a person PUT /api/v1/assessments/{id}/people/{personId}/exclusion assessments:write A participant is { person, managerId, status, tracks: { employee, manager }, completedAt, excludedFromAssessment, excludedFromDirectReports, includedAt } , where each track carries { status, completedAt, completedById } and progress is to_do , in_progress or completed . Person path slots accept an email or the opaque id. Exclusion has two independent forms : from the cycle entirely, or only from the manager’s direct-report view. The body carries either flag or both; an omitted flag is left as is. ​ Assessment grades (read-only) Operation Method and path Requires scope List a person’s assessment grades GET /api/v1/assessments/{id}/people/{personId}/grades assessments:read One row per career skill the person is assessed on: { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "section" : { "id" : "5" , "name" : "Safety" }, "career" : "Warehouse Operator" , "self" : { "grade" : { "id" : "7" , "grade" : 3 , "lab --- ## The Career object URL: https://help.skillsdb.com/api-docs/resources/career Quick Summary: A career is not a flat record — it is a complete competency model. The object below is the library entry; GET /api/v1/careers/{id}/definition returns the whole model in one call. ​ Attributes Field Type Description id string Opaque career id name string Career name description string | null Description icon string | null Icon identifier careerType object | null Reference { id, name } to the family it is grouped under levelCount integer Number of levels defined isCompleted boolean Informational flag set by the app’s career builder; nothing depends on it isApproved boolean Informational flag set by the app’s career builder and imports; nothing in this API depends on it createdAt / updatedAt string (ISO 8601 UTC) Timestamps; updatedAt may be null { "id" : "18" , "name" : "Maintenance Technician" , "description" : "Keeps the line running." , "icon" : "wrench" , "careerType" : { "id" : "3" , "name" : "Job Role" }, "levelCount" : 3 , "isCompleted" : false , "isApproved" : true , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } ​ The definition The full definition ( /careers/{id}/definition ) additionally carries settings , the company gradingScale , and complete levels , sections , skillGroups , skills and learnings arrays. Two things to know: Benchmarks are always resolved rungs — { "id": "46", "grade": 1, "label": "Basic awareness..." } , never a bare integer. The id references the company grading scale . Each skill carries its full configuration : section, groups, position, career-wide benchmark, its stored requirement configuration, evidence rules, expiry, and per-level activation for every level of the career. ​ The requirement object Each career skill carries a requirement object — the stored configuration , never a resolved boolean: { "isRequired" : true , "scope" : "going_forward" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "88" , "name" : "Dana Reviewer" } } Whether a skill is actually Required for a person is resolved against that person’s assignment date, so it belongs to person-scoped reads — a career is a company-level object, and no single boolean here can be true for everyone. isRequired reflects the stored flag with null resolved: only an explicit false turns a requirement off. scope is all (binds everyone holding the career) or going_forward (applies only to people assigned on or after effectiveFrom ). ​ How skills reach assignees A career’s skills are delivered to a person when they are assigned at a level , and only the skills active on that level are delivered. Attaching a skill to a career that already has levels activates it on every existing level, and adding a level activates every existing skill on it — whether the skill sits directly on the career, in a section or in a skill group. PATCH /careers/{id}/skills/{careerSkillId}/levels/{levelId} adjusts a skill’s per-level benchmark, or switches it off for a level. The isCompleted / isApproved flags play no part in this. ​ Editing sections, levels and skill groups PATCH /careers/{id}/sections/{careerSectionId} is partial: name , description and minimumRequiredSkills . Name and description belong to the library section the career attaches, so a rename shows on every career that uses it. The three reorder operations ( /levels/reorder , /sections/reorder , /skill-groups/reorder ) take { "ids": [...] } — every id of the collection in the desired order — the same field every reorder in this API takes. The resource-named fields they shipped with ( levelIds , sectionIds , skillGroupIds ) remain accepted as deprecated aliases. ​ Guarded deletes Deleting a career (or one of its levels) that would have consequences refuses with a 409 conflict reporting exactly what stands in the way; retrying with ?confirm=true proceeds deliberately. --- ## The Career Assignment object URL: https://help.skillsdb.com/api-docs/resources/career-assignment Quick Summary: An assignment links a person to a career at a level. Assigning grants that level’s learnings and attaches the career’s skills; unassigning records career history first, so a person’s past careers remain readable. ​ The assigned person Returned by GET /api/v1/careers/{id}/people . Field Type Description id string Opaque person id externalId string | null Your own identifier for this person — the Person resource’s externalId firstName / lastName string | null Name email string | null Email level object | null { id, name } — the level this person holds within the career assignedAt string (ISO 8601 UTC) | null Server-stamped when the assignment was created. Read-only initiationDate string (ISO 8601 UTC) | null Caller-supplied date the person actually begins in the career { "id" : "4821" , "externalId" : "E-10422" , "firstName" : "Ada" , "lastName" : "Lovelace" , "email" : "ada@example.com" , "level" : { "id" : "12" , "name" : "Level 2" }, "assignedAt" : "2026-03-11T08:22:10.000Z" , "initiationDate" : "2026-04-01T00:00:00.000Z" } The two dates have different owners. assignedAt is stamped by SkillsDB at the moment of the write and cannot be supplied; initiationDate is yours, and records when the person actually begins in the career. ​ The person’s career Returned by GET /api/v1/people/{personId}/careers — the {personId} slot takes the person’s email address (or the opaque id from any response). Previous (ended) assignments are included by default — pass ?includePrevious=false to exclude them. Field Type Description id string Opaque career id name string | null Career name careerType string | null The family the career belongs to isPrevious boolean true for an ended assignment, false for a current one assignedAt string (ISO 8601 UTC) | null When the assignment was created initiationDate string (ISO 8601 UTC) | null When the person began in the career skillsCount number | null Skills on the career { "id" : "318" , "name" : "Welder" , "careerType" : "Trades" , "isPrevious" : false , "assignedAt" : "2026-03-11T08:22:10.000Z" , "initiationDate" : "2026-04-01T00:00:00.000Z" , "skillsCount" : 24 } ​ The distribution Returned by GET /api/v1/careers/{id}/distribution . Counted server-side — do not page through the assigned-people list to derive these numbers. Field Type Description levels array Headcount per career level, in level order flags array Headcount per people-flag Each bucket is { id, label, count } , where id is null for the catch-all bucket (for example No Flag ). { "levels" : [{ "id" : "12" , "label" : "Level 2" , "count" : 17 }], "flags" : [{ "id" : null , "label" : "No Flag" , "count" : 17 }] } A credential bound to a manager sees only their span of control, so these counts reflect what the acting person is permitted to see — not necessarily the whole company. ​ Two rules that surprise integrations GET /api/v1/careers/{id}/people lists the career’s holders only — every row carries a level and an assignedAt ; an empty career is an empty list. GET /careers/{id}/distribution aggregates the same population server-side. Assigning is never an update. POST /api/v1/careers/{id}/people takes a list of people — identified by email address — each at their own level: { "people" : [{ "email" : "ada@example.com" , "levelId" : "12" }] } Anyone already holding the career is skipped silently — no error, and no level change. If you need to move someone, use PATCH /api/v1/careers/{id}/people/{personId} with { "levelId": "13" } — the {personId} slot takes the person’s email (or the opaque id from any response); an integration that re-assigns expecting a correction will do nothing at all. Assigning fans out. Beyond the assignment row, it grants every learning attached to the target level and attaches the career’s skills to the person. One call against a hundred people is a large write, not a small one — budget it against your rate limit. Unassigning mirrors the shape by email: DELETE /api/v1/careers/{id}/people with { "emails": ["ada@example.com", "grace@example.com"] } . Both assign and unassign accept at most 500 people per call — a larger array is rejected with a 400 validation-error before anything is written, so split bigger batches into chunks. --- ## The Career Type object URL: https://help.skillsdb.com/api-docs/resources/career-type Quick Summary: Career types organize the career library into families (for example Job Role and Group ). Full management over the API; a type cannot be deleted while careers still use it. ​ Attributes Field Type Description id string Opaque career type id name string Name description string | null Description createdAt / updatedAt string (ISO 8601 UTC) Timestamps; updatedAt may be null { "id" : "3" , "name" : "Job Role" , "description" : "Line-level roles." , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } --- ## The Certification object URL: https://help.skillsdb.com/api-docs/resources/certification Quick Summary: A certification is a library entry: a name, a description, the type it is grouped under, and the authority that issues it. Full management over the API. What a person holds — their record, its approval workflow, evidence and expiry — is the separate Person Certification resource. ​ Attributes Field Type Description id string Opaque certification id name string Name description string | null Description type object | null { id, name } of the certification type it is grouped under; null when untyped issuingAuthorityName string | null The organisation or body that issues it issuingAuthorityUrl string | null The issuing authority’s website labels array { id, name } of every label attached, in label order. Labels are attached and detached through the label endpoints holderCount integer People holding the certification — directly, or through a career that includes it holdersWithFileCount integer Holders who have attached at least one file as evidence createdAt / updatedAt string (ISO 8601 UTC) Timestamps; updatedAt may be null { "id" : "87" , "name" : "Forklift Operator Licence" , "description" : "Required for warehouse floor access." , "type" : { "id" : "4" , "name" : "Regulatory" }, "issuingAuthorityName" : "National Safety Council" , "issuingAuthorityUrl" : "https://www.nsc.org" , "labels" : [{ "id" : "12" , "name" : "Safety" }], "holderCount" : 14 , "holdersWithFileCount" : 9 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } A certification has no expiry of its own . Expiry belongs to a person’s record of it — two people can hold the same certification with different expiry dates. ​ Operations Operation Method and path Requires scope List certifications GET /api/v1/certifications certifications:read Get a certification GET /api/v1/certifications/{id} certifications:read Create a certification POST /api/v1/certifications certifications:write Update a certification PATCH /api/v1/certifications/{id} certifications:write Delete a certification DELETE /api/v1/certifications/{id} certifications:write ​ Listing Filterable by name , issuingAuthorityName and type (the type’s name); sortable by name and createdAt . See Filtering and Sorting . GET /api/v1/certifications?filter[type][eq]=Regulatory&sort=name ​ Creating and updating name is required on create; description , certificationTypeId , issuingAuthorityName and issuingAuthorityUrl are optional. A certificationTypeId must be one of the company’s types — an unknown id is a field-level validation-error , never a silent dangling reference. On PATCH , an omitted field is left untouched and an explicit null clears description , certificationTypeId , issuingAuthorityName or issuingAuthorityUrl . Labels are not part of this body: attach and detach them through the label endpoints. ​ Deleting Deletion is guarded. If anyone holds the certification, or any career includes it, the call answers 409 conflict with the counts: { "type" : "https://help.skillsdb.com/api-docs/errors/conflict" , "title" : "Conflict" , "status" : 409 , "detail" : "People hold this certification or careers include it. Retry with ?confirm=true to delete it anyway (holders keep their records as history; career links are removed)." , "confirmRequired" : true , "dependencies" : { "people" : 14 , "careers" : 2 } } Retry with ?confirm=true to proceed: the certification is soft-deleted and disappears from the library and from every career; holders’ records stay as history. An unheld, unlinked certification deletes immediately with 204 . ​ Permissions Every call is the intersection of the key’s scopes and what the acting person may do in the app. Reads, creates and updates are broadly permitted; delete is restricted to global administrators , and a key acting as a person who cannot delete receives insufficient-permissions . Two roles hold no certification permissions at all in the app today, so a key bound to a person in one of them is refused on every certification endpoint with the same problem type — bind the key to a person who can manage certifications. ​ Related errors not-found — the id does not exist in your company (another company’s certification answers the same 404) validation-error — a missing name, an over-long field, or an unknown certificationTypeId conflict — the guarded delete above insufficient-scope / insufficient-permissions — see Permissions --- ## The Certification Type object URL: https://help.skillsdb.com/api-docs/resources/certification-type Quick Summary: Certification types organise the certification library into families (for example Regulatory and Vendor ). Each type carries its display position and how many certifications use it. A type that is still in use cannot be deleted without confirming. ​ Attributes Field Type Description id string Opaque certification type id name string Name description string | null Description position integer 1-based display position within the company certificationCount integer Live certifications grouped under this type createdAt / updatedAt string (ISO 8601 UTC) Timestamps; updatedAt may be null { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ​ Operations Operation Method and path Requires scope List certification types GET /api/v1/certification-types certifications:read Get a certification type GET /api/v1/certification-types/{id} certifications:read Create a certification type POST /api/v1/certification-types certifications:write Update a certification type PATCH /api/v1/certification-types/{id} certifications:write Reorder certification types POST /api/v1/certification-types/reorder certifications:write Delete a certification type DELETE /api/v1/certification-types/{id} certifications:write The list is always in display order ( position ascending) and takes no filters. ​ Creating and updating name is required on create (up to 100 characters); description is optional. A new type is placed at the end of the order. On PATCH , an omitted field is left untouched and an explicit null clears the description. ​ Reordering POST /api/v1/certification-types/reorder { "ids" : [ "4" , "2" , "7" ] } The body must list every certification type id of the company exactly once, in the desired order; the response is the full list in its new order. A partial list, a duplicate, or an id from another company is 422 unprocessable . ​ Deleting Deletion is guarded. While certifications still use the type, the call answers 409 conflict : { "type" : "https://help.skillsdb.com/api-docs/errors/conflict" , "title" : "Conflict" , "status" : 409 , "detail" : "Certifications still use this type. Retry with ?confirm=true to delete it anyway (those certifications are left without a type)." , "confirmRequired" : true , "dependencies" : { "certifications" : 6 } } Retry with ?confirm=true to proceed: the type is soft-deleted and each certification that used it is left with type: null . An unused type deletes immediately with 204 . ​ Permissions Any person who can read certifications in the app can read types. Creating, updating, reordering and deleting types is restricted to global administrators ; a key acting as anyone else receives insufficient-permissions on those operations even when it holds certifications:write . ​ Related errors not-found — the id does not exist in your company validation-error — a missing or over-long name unprocessable — an incomplete or foreign reorder list conflict — the guarded delete above --- ## The Flag objects URL: https://help.skillsdb.com/api-docs/resources/flag Quick Summary: There are TWO flag systems sharing no tables: people flags ( /api/v1/people-flags ) tag a person; skill flags ( /api/v1/skill-flags ) tag a person at a career, section, skill-group or skill scope. A flag is the company-configured type; a flag assignment is a person carrying one. ​ Attributes (both systems) Field Type Description id string Opaque flag id name / description / color — Display fields isEnabled boolean See the disable warning below isSystemDefault boolean System defaults cannot be deleted, only disabled position number | null Order within the list designatesTrainer boolean Skill flags only — turns assignment into a competency signal driving trainer counts, metrics and the training approver pool Disabling hides existing assignments — it does not merely block new ones. Every assignment of a disabled flag disappears from the assignment reads, and for skill flags also from trainer counts, metrics and the training approver pool: someone carrying a trainer-designating flag stops counting as a trainer the moment it is disabled. No rows are deleted — re-enabling restores everything. An integrator reconciling assignments will otherwise see rows vanish with no corresponding delete. ​ People flags CRUD plus POST /{id}/enable , POST /{id}/disable , POST /reorder , GET /{id}/dependencies , and a guarded DELETE /{id} (409 with the holder count; ?confirm=true proceeds). Assignments: GET /people-flags/{id}/people , and per person GET|POST|DELETE /people/{id}/people-flags — the {id} slot takes the person’s email address (or the opaque id from any response), and each assignment carries who assigned it and when. PATCH /{id} is a partial update on both flag kinds: send only the fields that change ( name , description , color , and designatesTrainer on skill flags); what is left out keeps its value. POST still requires name . Visibility exists only for people flags : one company-wide setting per audience at GET|PATCH /people-flags/visibility (administrators always see them — not configurable), and GET /people-flags/visibility/me resolves the answer for the acting identity. ​ Skill flags The same lifecycle surface plus PATCH /{id}/trainer-designation . Dependencies and the guarded delete report counts per scope . Assignments live at /api/v1/skill-flag-assignments/{scope} where scope is careers , sections , skill-groups or skills — query with filters ( ?email= scopes to one person), POST applies in bulk and DELETE removes in bulk, both naming the people by email address : { "careerId" : "18" , "flagId" : "7" , "emails" : [ "ada@example.com" , "grace@example.com" ] } Assignment rows in responses carry an opaque personId — use the person’s email when making requests. The skill scope is not career-relative. Career, section and skill-group assignments carry the career; a skill-scope assignment keys off the skill alone and returns careerId: null . The four scopes are deliberately not squeezed into one shape. Trainer tracking: GET /api/v1/skill-groups/{id}/trainer-count counts people carrying an enabled trainer-designating flag for the group. ​ Not published FlagType — every assignment row internally duplicates the flag’s display name as a string, and it drifts when the flag is renamed. The API publishes the flag reference only. --- ## The Grading Scale URL: https://help.skillsdb.com/api-docs/resources/grading-scale Quick Summary: One scale per company. Every benchmark on every career, and every achieved grade, references a rung of this scale by id. A new company starts with an empty scale — add rungs before grading anything. Once any grade in the company references the scale, a rung’s numeric grade is locked and rungs can no longer be removed; labels, descriptions and the active flag stay editable. ​ Attributes (per rung) Field Type Description id string Opaque rung id — what benchmarks reference grade integer The numeric grade value, used for gap computation label string Short label description string | null Long description isActive boolean Inactive rungs stay resolvable but are not offered for new grades { "id" : "46" , "grade" : 1 , "label" : "Basic awareness and demonstrated capacity to learn" , "description" : "1- Possess basic knowledge" , "isActive" : true } ​ Writing the scale Operation Method and path Scope Read the scale GET /api/v1/grading-scale careers:read Add a rung POST /api/v1/grading-scale careers:write Update a rung PATCH /api/v1/grading-scale/{id} careers:write Remove a rung DELETE /api/v1/grading-scale/{id} careers:write POST takes { "grade": 3, "label": "Proficient", "description": "..." } — one rung per call, the grade unique within the company. The rung is active and immediately usable as a gradeId on self-, manager- and benchmark grades. A grade that already exists is a 409 : update that rung instead. PATCH is partial: any of grade , label , description , isActive . Once the scale is in use, changing grade is a 409. DELETE answers 204 for a rung nothing references and a 409 once the scale is in use — deactivate the rung instead. ​ Why the API never returns a bare benchmark integer A rung carries two integers — its id and its grade value — and they routinely differ. A bare benchmark: 4 could denote a rung whose actual grade is 2, and an integrator would compute gaps against the wrong number silently. The API therefore always returns the resolved rung: { id, grade, label } . --- ## The Label object URL: https://help.skillsdb.com/api-docs/resources/label Quick Summary: A label is a company-wide tag with a name, colour, icon and description. Labels form a tree of any depth, and the same label can be attached to skills, certifications, learning items and careers — one pool, four attachment points. Attaching is idempotent and all-or-nothing; deleting is guarded. ​ Attributes Field Type Description id string Opaque label id name string Name (up to 50 characters) description string | null icon string | null Icon identifier color string Display colour position integer 1-based position among its siblings — ordering is scoped per parent, not company-wide parentId string | null The parent label; null for a top-level label createdAt / updatedAt string | null The tree read returns the same object with a children array, in position order. { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ​ Operations ​ Library Operation Method and path Requires scope List labels GET /api/v1/labels labels:read Get a label GET /api/v1/labels/{id} labels:read Create labels POST /api/v1/labels labels:write Update a label PATCH /api/v1/labels/{id} labels:write Reorder labels POST /api/v1/labels/reorder labels:write Delete a label DELETE /api/v1/labels/{id} labels:write The flat list is filterable by name , description and parentId , and sortable by name and position . Create is plural by nature: { "labels": [{ name, color, description?, icon?, parentId? }] } in, the created labels out. color is required. Each new label is placed at the end of its sibling group. Update takes name , description , icon and color ; an explicit null clears the description or icon. Moving a label is its own operation (below). Reorder sets positions within one sibling group: { "parentId": "4" | null, "ids": [...] } must list every label of that group exactly once, in the desired order. A partial or foreign list is 422 unprocessable . Delete is guarded. If any object carries the label, or it has children, the call answers 409 conflict : { "type" : "https://help.skillsdb.com/api-docs/errors/conflict" , "title" : "Conflict" , "status" : 409 , "detail" : "The label is attached to objects or has child labels. Retry with ?confirm=true to delete it anyway: it is removed from every object and its children become top-level labels." , "confirmRequired" : true , "dependencies" : { "skills" : 14 , "certifications" : 2 , "learningItems" : 0 , "careers" : 3 , "children" : 2 }, "childrenPromotedToTopLevel" : 2 } Retry with ?confirm=true : the label is stripped from every object and each child is promoted to top level, renumbered after the existing roots — what the app does silently, now stated. ​ Hierarchy Operation Method and path Requires scope List labels as a tree GET /api/v1/labels/tree labels:read List top-level labels GET /api/v1/labels/top-level labels:read List a label’s children GET /api/v1/labels/{id}/children labels:read Reparent a label PATCH /api/v1/labels/{id}/parent labels:write Reparent takes { "parentId": "4" } to move the label, or { "parentId": null } to promote it to top level. It refuses with a 409 when the proposed parent is the label itself or one of its own descendants — the server checks the whole tree, not just the browser. ​ Attachment The same three operations against each kind of object: Operation Method and path Requires scope List an object’s labels GET /api/v1/{skills|certifications|learning-items|careers}/{id}/labels labels:read Attach labels POST /api/v1/{skills|certifications|learning-items|careers}/{id}/labels labels:write Detach labels DELETE /api/v1/{skills|certifications|learning-items|careers}/{id}/labels labels:write List labels in use for a kind GET /api/v1/labels/in-use?kind=skill|certification|learning_item|career labels:read Attach and detach take { "labelIds": ["12", "15"] } and answer the object’s current labels. Attaching a label the object already carries succeeds without change , and the call applies wholly or not at all — a retry after a network failure is safe. Detaching a label the object does not carry is likewise a no-op. An unknown label is a 404; an unknown or foreign object is the same 404. The in-use read returns only labels attached to at least one live object of the kind — the read that drives filter options — and works the same way for all four kinds. ​ Permissions Any person who can read labels in the app can read them here. Creating, updating, reordering, reparenting, deleting, attaching and detaching are restricted to global administrators ; a key acting as anyone else receives insufficient-permissions even when it holds labels:write . ​ Excluded People, skill, section and skill-group flags are a separate feature (see Flag ). The labelled objects themselves belong to their own resources. CSV label import is an in-app path. ​ Related errors not-found — the label, or the object being labelled, is not in your company validation-error — a missing name or colour, an unknown parent on create or reparent, a bad kind unprocessable — an incomplete reorder list conflict — a reparent that would create a cycle; the guarded delete --- ## The Learning Item object URL: https://help.skillsdb.com/api-docs/resources/learning-item Quick Summary: A learning item is an entry in your company’s training catalogue. It carries a title, an optional link or file, a learning type and up to four further references (provider, format, audience, course level) drawn from the company’s reference lists . Items are attached to skills and careers, labelled, and assigned to people as learning plans . Deleting is guarded. ​ Attributes Field Type Description id string Opaque learning item id title string description string | null url string | null Link to the content. Unique within the company durationHours number | null cost number | null costDescription string | null Free text next to the cost type { id, name } | null Learning type (reference list) provider { id, name } | null Training provider (reference list) format { id, name } | null Training format (reference list) audience { id, name } | null Training audience (reference list) courseLevel { id, name } | null Training course level (reference list) imageUrl string | null Display image hasFile boolean An attached file exists; fetch it with the download-url operation referenceId string | null Caller-supplied external identifier labels [{ id, name }] Labels attached to the item skillNames string[] Names of the skills the item is attached to careerNames string[] Names of the careers the item appears on assignedCount / inProgressCount / completedCount integer Learning plans for active people, by state averageRating number | null Mean of the thumbs ratings (0 down, 1 up, 2 double up); null until someone rates createdAt / updatedAt string | null The five references are published as { id, name } pairs resolved against the reference lists. The legacy free-text provider, level, format and audience columns the app still stores are not part of the object. { "id" : "512" , "title" : "Forklift Safety Refresher" , "description" : "Annual refresher for licensed operators." , "url" : "https://learn.example.com/forklift" , "durationHours" : 2.5 , "cost" : 120 , "costDescription" : null , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "1" , "name" : "Acme Learning" }, "format" : null , "audience" : null , "courseLevel" : null , "imageUrl" : null , "hasFile" : false , "referenceId" : "LMS-4471" , "labels" : [{ "id" : "12" , "name" : "Safety" }], "skillNames" : [ "Forklift Operation" ], "careerNames" : [], "assignedCount" : 40 , "inProgressCount" : 12 , "completedCount" : 25 , "averageRating" : 1.6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ​ Operations ​ Catalogue Operation Method and path Requires scope List learning items GET /api/v1/learning-items learning:read Get a learning item GET /api/v1/learning-items/{id} learning:read Create a learning item POST /api/v1/learning-items learning:write Create a learning item with a file POST /api/v1/learning-items/with-file learning:write Update a learning item PATCH /api/v1/learning-items/{id} learning:write Delete a learning item DELETE /api/v1/learning-items/{id} learning:write The list is filterable by title , id , labels , people , rating , cost , duration and skill — the app’s library filters under the same names — and sortable by title , cost , duration , rating and id . Pending and rejected suggestions are not part of the catalogue. Create needs title and typeId ; providerId , formatId , audienceId , courseLevelId , labelIds and skillIds are optional. A reference id that is not an entry of the company’s list is a field-level validation error . Create with a file is the two-step path: send the same body plus fileName , receive { item, uploadUrl } , then PUT the file’s bytes to uploadUrl (a short-lived pre-signed URL). hasFile is true from the moment the item exists. Update is partial: a field that is absent is left alone, an explicit null clears it. A url already used by another item is a 409 conflict . Delete is guarded. If the item is assigned to anyone or attached to a skill or career the call answers 409 conflict : { "type" : "https://help.skillsdb.com/api-docs/errors/conflict" , "title" : "Conflict" , "status" : 409 , "detail" : "The learning item is assigned to people or attached to skills or careers. Retry with ?confirm=true to delete it anyway: every assignment and attachment is removed with it." , "confirmRequired" : true , "dependencies" : { "learningPlans" : 40 , "skills" : 2 , "careers" : 1 } } Retry with ?confirm=true to delete the item together with every assignment and attachment. ​ Skills Operation Method and path Requires scope List an item’s skills GET /api/v1/learning-items/{id}/skills learning:read Attach a skill POST /api/v1/learning-items/{id}/skills learning:write Feature or unfeature for a skill PATCH /api/v1/learning-items/{id}/skills/{skillId} learning:write Detach a skill DELETE /api/v1/learning-items/{id}/skills/{skillId} learning:write Attach takes { "skillId": "77", "featured": true } ( featured optional) and is idempotent — attaching a skill the item already carries succeeds without change. Detaching a skill the item does not carry is a no-op. Every call answers the item’s current skills, each as { skill: { id, name }, featured } . A featured item is shown first for the skill. ​ Careers, labels, ratings and file Operation Method and path Requires scope List the careers an item appears on GET /api/v1/learning-items/{id}/careers learning:read Replace an item’s labels PUT /api/v1/learning-items/{id}/labels learning:write Get rating counts GET /api/v1/learning-items/{id}/ratings learning:read Get a download URL for the file GET /api/v1/learning-items/{id}/download-url learning:read Replace labels takes { "labelIds": ["12", "15"] } and sets the complete set; an empty list clears every label. Incremental attach and detach live on the Label resource. Ratings answers { thumbsDown, thumbsUp, doubleThumbsUp } . Download URL answers a short-lived pre-signed URL; an item without a file is a 404 . ​ Permissions Any person who can see the training library in the app can read items her --- ## The Learning Plan object URL: https://help.skillsdb.com/api-docs/resources/learning-plan Quick Summary: A learning plan assigns a catalogue item to a person. It shares nothing with training records — the two are both “what has this person done”, never one shape. ​ Attributes Field Type Description id string Opaque plan id personId string The person the plan belongs to — an opaque response id; use the person’s email address when making requests learning object Reference to the catalogue item state string Lifecycle only: not_started , in_progress , completed , archived dueDate / isPastDue — Due status is derived from the date, never a stored lifecycle state dueDateSetById string | null Who set the due date — the authority rule below depends on it rating string | null positive , strongly_positive , negative , or null careerAssignmentId string | null The career assignment the plan arose from, when career-linked assignedAt / startedAt / completedAt — Stamped by state transitions ​ Rules the API enforces A due date cannot be set in the past. A due date set by the person’s manager cannot be changed by the person it belongs to. A rating is the plan owner’s own feedback : the acting person behind the credential can rate only their own plans — even an admin identity is refused (403). Sending rating: null clears the rating; clearing is a real write, never a silent success. ​ Assignment GET|POST|DELETE /api/v1/learning-items/{id}/people mirror the career-assignment shape: who has the item, bulk assign, bulk unassign. Assign and unassign identify people by email address — { "emails": ["ada@example.com", "grace@example.com"] } , at most 500 per call. A person’s plans are read at GET /api/v1/people/{id}/learning-plans , where {id} takes the email (or the opaque id from any response). Careers can also assign learning as a side effect (assigning a career grants the target level’s learnings), so a plan can appear without a direct assignment call — careerAssignmentId tells you which career it came from. --- ## The Learning Reference List object URL: https://help.skillsdb.com/api-docs/resources/learning-reference-list Quick Summary: A learning item points at up to five reference entries: its type, provider, format, audience and course level. Each list is company-defined, ordered, and served under one parameterised path, /api/v1/learning-reference/{list} , with the same shape and operations for all five. Deleting an entry in use is guarded. ​ Lists {list} Describes On the item as learning-types What kind of content (course, video, document…) type — required on every item training-providers Who delivers it provider training-formats How it is delivered (online, classroom…) format training-audiences Who it is for audience training-course-levels Difficulty courseLevel Any other value for {list} is a validation error . ​ Attributes Field Type Description id string Opaque entry id name string description string | null position integer 1-based position in the list’s display order referenceCount integer Learning items (and suggestions) using the entry createdAt string | null { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } ​ Operations Operation Method and path Requires scope List entries GET /api/v1/learning-reference/{list} learning:read List entries in use GET /api/v1/learning-reference/{list}/in-use learning:read Get an entry GET /api/v1/learning-reference/{list}/{id} learning:read Create an entry POST /api/v1/learning-reference/{list} learning:write Update an entry PATCH /api/v1/learning-reference/{list}/{id} learning:write Reorder a list POST /api/v1/learning-reference/{list}/reorder learning:write Delete an entry DELETE /api/v1/learning-reference/{list}/{id} learning:write Lists come back in display order and are filterable by name ( eq , neq , like , in ) and sortable by name and position . The in-use read returns only entries with a referenceCount above zero — the read that drives filter options. Create takes { "name": "Workshop", "description": "…" } and places the entry at the end of the list. Update takes name and description . Reorder takes { "ids": ["3", "1", "2"] } and must list every entry of the list exactly once, in the desired order; a partial, duplicated or foreign list is 422 unprocessable . The response is the whole list with new positions. Delete is guarded. If any learning item uses the entry the call answers 409 conflict with confirmRequired: true and dependencies: { "learningItems": 14 } . Retry with ?confirm=true : the entry is removed and the reference is cleared from every item — the item’s type , provider , format , audience or courseLevel becomes null . ​ Permissions Any person who can see the training library can read the lists. Creating, updating, reordering and deleting entries follows the same rule as authoring learning items : global administrators, managers, full-access users and employees may change them; administrators, directors and executives receive insufficient-permissions . Deleting is restricted to global administrators. Every operation is company-scoped: an entry of another company is a 404 to read, update, reorder or delete. ​ Related errors validation-error — an unknown {list} , a missing name, an unsupported filter operator not-found — the entry is not in your company unprocessable — an incomplete reorder list conflict — the guarded delete --- ## The Learning Suggestion object URL: https://help.skillsdb.com/api-docs/resources/learning-suggestion Quick Summary: A learning suggestion is a proposed catalogue entry. Anyone who can see the training library may submit one; the submitter or a global administrator may revise it while it is pending; only a global administrator approves or rejects it. On approval the suggestion becomes a learning item with the same id . A rejected or pending suggestion is never a catalogue item. ​ Attributes Field Type Description id string Opaque id — becomes the learning item id on approval title string description / url string | null durationHours / cost number | null type / provider / format / audience / courseLevel { id, name } | null References into the reference lists referenceId string | null note string | null The submitter’s note to the reviewer suggestedSkillIds string[] Skills the item is proposed for; attached on approval suggestedCareerIds string[] Careers the item is proposed for; attached on approval status pending | approved | rejected submittedById / submittedAt string | null approvedById / approvedAt string | null Set on approval rejectedById / rejectedAt / rejectionReason string | null Set on rejection modifiedOnApproval boolean True when the administrator changed the submission before approving it. The original submission is retained internally and is not published { "id" : "530" , "title" : "Advanced Rigging" , "description" : null , "url" : "https://learn.example.com/rigging" , "durationHours" : 8 , "cost" : 450 , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : null , "format" : null , "audience" : null , "courseLevel" : null , "referenceId" : null , "note" : "Needed for the crane team." , "suggestedSkillIds" : [ "77" ], "suggestedCareerIds" : [], "status" : "pending" , "submittedById" : "1042" , "submittedAt" : "2026-03-01T09:00:00.000Z" , "approvedById" : null , "approvedAt" : null , "rejectedById" : null , "rejectedAt" : null , "rejectionReason" : null , "modifiedOnApproval" : false } ​ Operations Operation Method and path Requires scope List suggestions GET /api/v1/learning-suggestions learning:read Get a suggestion GET /api/v1/learning-suggestions/{id} learning:read Submit a suggestion POST /api/v1/learning-suggestions learning:write Revise a pending suggestion PATCH /api/v1/learning-suggestions/{id} learning:write Approve POST /api/v1/learning-suggestions/{id}/approve learning:write Reject POST /api/v1/learning-suggestions/{id}/reject learning:write The list is filterable by title , status (the public values pending , approved , rejected ), submittedBy (a person’s email ), cost and createdAt , and sortable by title , createdAt and cost . A key acting as a manager lists only the suggestions of the manager’s reports, as in the app. Submit needs title ; typeId , the other reference ids, note , skillIds and careerIds are optional. The result is pending . Revise takes the same fields as submit (without note ) and applies to pending suggestions only; a decided suggestion is a 409 conflict . Approve with an empty body approves the submission as-is. Any field present in the body is applied first — the administrator’s modification — and modifiedOnApproval becomes true. On approval the suggested skills and careers are attached and the item appears in the catalogue under the same id. Reject requires { "reason": "…" } ; the reason is recorded and the suggestion stays visible with status: rejected . ​ Permissions Any person who can see the training library may read and submit suggestions. Revising a pending suggestion is allowed to the person who submitted it and to global administrators. Approving and rejecting are restricted to global administrators ; any other acting person receives insufficient-permissions even when the key holds learning:write — this includes the submitter. ​ Related errors not-found — the suggestion is not in your company, or the id names a catalogue item that was never a suggestion validation-error — a missing title or rejection reason, an unknown reference id, an unknown status filter value conflict — a revision or decision on a suggestion that is no longer pending insufficient-permissions — the acting person may not decide, or may not revise someone else’s submission --- ## The Org Structure objects URL: https://help.skillsdb.com/api-docs/resources/org-structure Quick Summary: Org structure is two unrelated things. Eleven flat dimensions — businessUnits, divisions, businessRegions, countries, states, cities, sites, buildings, departments, teams, shifts — say where someone sits ; the manager hierarchy says who they report to . They share nothing, and the dimensions have no parent-child structure between them. ​ Dimension values Every dimension behaves identically. A value is { id, name, isActive } : GET /api/v1/org/dimensions — the eleven keys. GET /api/v1/org/{dimension} — every value, deactivated ones included. POST /api/v1/org/{dimension} — create (name only; no ordering exists). PATCH /api/v1/org/{dimension}/{id} — rename, or isActive: false to deactivate; isActive: true reactivates. DELETE /api/v1/org/{dimension}/{id} — deactivates the value. Org values are retired, never removed, exactly as in the app: DELETE and PATCH { "isActive": false } are the same operation. It is idempotent (an already-inactive value returns 204 ) and needs no confirmation; the confirm query parameter is deprecated and ignored. GET /api/v1/org/{dimension}/{id}/usage — how many people hold the value, before deactivating it. GET /api/v1/org/{dimension}/{id}/people — everyone holding the value. ​ What deactivation does Deactivating a value through the API does what deactivating it in Settings > Org Schema does: The value leaves every person’s profile — its membership rows are removed, so GET .../usage reports peopleCount: 0 and GET .../people is empty. Draft surveys and draft assessments that targeted the value drop it. Launched ones are untouched. The value stays readable with isActive: false and reappears in GET /api/v1/org/{dimension} as inactive. PATCH { "isActive": true } brings it back. The dimension’s history records who deactivated it (the key’s acting person). Buildings are the app’s one exception: deactivating a building only flips its flag (no membership removal, no history), and the API mirrors that. One legacy edge case, also inherited from the app: a value whose active flag was never set reads as active, but deactivating it only sets the flag. The app runs its cleanup only when the flag was explicitly true , so such a value keeps its memberships. GET .../usage shows whether that happened. Deactivation never clears the legacy single-value columns on the person record ( departments and businessRegions ); usage.personRecordCount keeps that drift visible. ​ A person’s placement Placement is many-to-many — someone can belong to two sites or three teams. It lives on the Person resource: GET|POST|DELETE /api/v1/people/{id}/org-schema (additive attach / explicit detach) and PUT /api/v1/people/{id}/org-schema/{dimension} to replace one dimension exactly. Countries come from a fixed list. POST /api/v1/org/countries takes a name that must match a country exactly as GET /api/v1/countries lists it (the same global list the app offers); any other name is a 400 on name . The other ten dimensions accept any name. One representation is published. Internally five org facts also exist in a second, legacy form on the person record (single-value department and business-region columns, free-text city/state/country strings). The API reads and writes the membership form only; the usage read reports legacy-column references for departments and businessRegions so any drift is visible. ​ Manager hierarchy GET /api/v1/org/manager-tree — the company’s reporting hierarchy as flat parent-pointer rows ordered by depth (roots at level 0), company-scoped, paginated. GET /api/v1/people/{id}/span-of-control — one person’s subtree, subject included at level 0. Setting a person’s manager is PATCH /api/v1/people/{id}/manager on the Person resource. --- ## The Person object URL: https://help.skillsdb.com/api-docs/resources/person Quick Summary: People are the company’s workforce records. What a caller can see and change is always bounded by the acting identity behind the credential — a manager’s credential sees their span of control, an admin’s their departments. ​ Attributes Field Type Description id string Opaque person id externalId string | null The customer’s own identifier — the field an integration should key on . Customer-supplied and not guaranteed unique firstName / lastName string Mandatory email string | null The person identifier on this API — the value requests use to address a person. Unique across all of SkillsDB , not just your company; changed only through its own operation accessLevel object | null { slug, name, isAssignable } — never the stored integer, which does not rank manager object | null Reference { id, name } to another person. Set with managerEmail on create, or through the /manager operation jobTitle object | null Reference to a company job title peopleType object | null Reference to a company people type, plus expiresAt orgSchema object Memberships across eleven independent dimensions, each a list of references Contact fields string | null businessPhone , mobilePhone , homePhone , address , city , stateProvince , postalCode , country (reference), webPage externalCompanyName string | null Free-text third-party company name — never a tenant reference nextAvailableDate string | null ISO 8601 UTC isActive boolean Always explicit — legacy rows with no stored value read as active inactiveAt string | null Stamped on deactivation createdAt / createdById / updatedAt / updatedById — Read-only audit fields Email uniqueness is global: creating a person — or changing an email — with an address already registered to another SkillsDB company returns a 409 conflict whose message never names the holder. ​ Addressing a person Every /people/{id} -style path slot on this API takes the person’s email address — the primary, documented form — or the opaque id from any response (ids are all digits, so the two forms never collide). Request fields that reference a person are email fields: managerEmail on create, { "email": ... } on the manager operation, delegatedApproverEmail on trainings. Resolution is bounded by your company — an email held by another company is indistinguishable from one that does not exist. Where the identifier is a path segment ( /people/{id} ), that is a 404 ; where it is a request field ( managerEmail , people[].email , emails , delegatedApproverEmail ), it is a 400 naming the field with code unknown_person — a 404 on an existing route would read to generated clients as the route being missing. If your data holds case- or whitespace-variant duplicates of one address, the API answers 409 rather than pick a record: resolve the duplicates, or use the opaque id. ​ Access levels Four levels are assignable — basic , manager , admin , fullaccess — and three are legacy ( executive , globaladmin , director ): readable on people who hold them, never writable. GET /api/v1/access-levels publishes the full set. The grant cap: the API refuses (403) any attempt to grant an access level above the acting identity’s own. A credential can never mint a person who exceeds its own acting person. ​ Updates are truly partial PATCH /api/v1/people/{id} is field-presence based: absent means unchanged, explicit null means clear. Email, access level, manager, job title, people type and active status each move through their own operation ( /email , /access-level , /manager , /job-title , /people-type , /activate , /deactivate ) — updating a phone number never requires knowing or restating anything else. The manager operation takes { "email": "lead@example.com" } — the manager’s email address, or null to clear the manager. ​ Reporting structure GET /people/{id}/direct-reports — one level only. GET /people/{id}/span-of-control — the whole subtree, paginated, each entry carrying level . The subject is included at level 0 , so a headcount over the rows is off by one if that is forgotten. PATCH /people/{id}/manager refuses a reporting loop with a 409 carrying managerPersonId , managerName and reportDepth ; GET /people/managers?excludeSubtreeOf=ada@example.com (an email, or an opaque id) prevents selecting one in the first place. ​ Org schema Eleven independent many-to-many dimensions: businessUnits, divisions, businessRegions, countries, states, cities, sites, buildings, departments, teams, shifts. POST /people/{id}/org-schema is additive only — it never removes a membership, and ids already held are ignored. DELETE /people/{id}/org-schema removes named memberships. PUT /people/{id}/org-schema/{dimension} replaces one dimension with exactly the supplied list — the shape an HRIS sync needs. ​ Additional skills A person’s directly-assigned skills — distinct from the ones a career confers, and the relationship recording a training requires: GET /api/v1/people/{personId}/skills — the direct assignments, each with id , name , description and isCertification . POST /api/v1/people/{personId}/skills with { "skillIds": ["512"] } — assigns existing catalogue skills. Already-assigned skills are skipped, never re-graded; the response reports affected and skipped . DELETE /api/v1/people/{personId}/skills with the same body — removes direct assignments (with their grades and flags), writing history first. Career-conferred skills are managed through the career, not here. These operations carry the skills:read / skills:write scopes — the assigned object’s scope governs, the same convention career assignment uses. Who may assign follows the app’s own rule: a key acting as the person assigns to themselves, a manager within their span, an admin anywhere in the company. ​ No delete Deleting a person does not exist on the API, deliberately: the product’s delete is an irreversible hard delete across roughly fifty tables. POST /people/{id}/deactivate is the lifecycle operation — it retains the person and their history. SCIM and this API are --- ## The Person Certification object URL: https://help.skillsdb.com/api-docs/resources/person-certification Quick Summary: A person certification is one person’s holding of a certification : its workflow state, issued and expiry dates, identifier, evidence and history. Record it, move it through approval, renew it, and report coverage across a population. Expiry is derived from the date, never from the status — an approved certification stays approved in storage after its date passes, so every read carries a separate expiry block. ​ Attributes Field Type Description person object { id, email, firstName, lastName } certification object { id, name, type } — the library entry and its type name status string | null assigned , awaiting_approval , approved or denied ; null when the record has never been graded certified boolean | null Pass/fail flag. Certifications are not graded on the company scale — there is no rung or benchmark identifier string | null Certificate number issued by the authority issuedAt / expiresAt string | null Issued and expiry dates (ISO 8601 UTC) expiry object { state, daysUntil } — state is none , valid , expiring or expired , derived at read time; daysUntil is negative once expired scoreDescription string | null Free-text score description issuingAuthority string | null The authority recorded on this person’s certification heldDirectly boolean Held as a direct assignment careers array of string Careers the certification is derived through. A certification can be held both ways at once attachmentCount integer Evidence on the live record labels array { id, name } of the library certification’s labels submittedAt / approvedAt / deniedAt string | null Decision timestamps The detail read adds attachments : { id, type, label, url, createdAt } where type is file or link and url is set for links only. { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "valid" , "daysUntil" : 268 }, "scoreDescription" : null , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 1 , "labels" : [{ "id" : "12" , "name" : "Safety" }], "submittedAt" : "2025-06-02T09:00:00.000Z" , "approvedAt" : "2025-06-03T10:00:00.000Z" , "deniedAt" : null } ​ Operations Person path slots ( {personId} ) accept the person’s email address or the opaque id from any response. ​ A person’s certifications Operation Method and path Requires scope List a person’s certifications GET /api/v1/people/{personId}/certifications certifications:read Get one of a person’s certifications GET /api/v1/people/{personId}/certifications/{certificationId} certifications:read List certifications available to a person GET /api/v1/people/{personId}/available-certifications certifications:read List a person’s certification history GET /api/v1/people/{personId}/certifications/{certificationId}/history certifications:read The list is filterable by status ( eq / in ) and expiry ( eq / in over none , valid , expiring , expired ); the page total is the count for the same filters. A certification held directly and through a career appears once, with heldDirectly: true and its careers listed. The history is every superseded attempt — archived by renewal ( endedAs: "expired" ) or by resubmission after a denial ( endedAs: "denied" ) — each with its dates, identifier, who assigned, submitted, approved or denied it and when, and the evidence that stayed with that attempt. Read it with the live record for the full story. ​ Recording and maintaining Operation Method and path Requires scope Record (or assign) a certification POST /api/v1/people/{personId}/certifications certifications:write Update a person’s certification PATCH /api/v1/people/{personId}/certifications/{certificationId} certifications:write Submit for approval POST /api/v1/people/{personId}/certifications/{certificationId}/submit certifications:write Approve POST /api/v1/people/{personId}/certifications/{certificationId}/approve certifications:write Deny POST /api/v1/people/{personId}/certifications/{certificationId}/deny certifications:write Renew POST /api/v1/people/{personId}/certifications/{certificationId}/renew certifications:write Unassign DELETE /api/v1/people/{personId}/certifications/{certificationId} certifications:write Recording. certificationId is required. With nothing else the record is the light assign — it lands in assigned with no dates, identifier or evidence. Add issuedAt , expiresAt , identifier , scoreDescription , certified , issuingAuthority , one link and up to ten files to record it in full. Each file returns a pre-signed upload URL in uploads ; upload the bytes to it. A person who already holds the certification is a 409 — update or renew instead. Two fields can be set here that no app screen can set: scoreDescription , and certified: false . The app reads both, so API-recorded certifications may carry values app-recorded ones never do. The state machine. assigned → awaiting_approval (submit) → approved or denied ; denied → awaiting_approval (submit again); approved is terminal except through renewal. Approve also accepts assigned directly, matching the app’s manager path. A transition the current state does not allow is a 409 . Updating is allowed while assigned , awaiting_approval or denied ; an approved certification is closed to edits (409) and must be renewed. Omitted fields are untouched; an explicit null clears issuedAt , expiresAt , identifier , scoreDescription or issuingAuthority . expiresAt may not precede issuedAt . Renewing archives the current attempt and its evidence to history as expired , resets the record to assigned , and records the new issue. The identifier and issuing authority carry forward unless replaced; the previous result does no --- ## The Person Skill object URL: https://help.skillsdb.com/api-docs/resources/person-skill Quick Summary: A person skill is a skill on a person’s profile. It carries the person’s self grade and the manager’s grade (each with years of experience), a resolved benchmark, the not-applicable and focus flags, and its origin — attached directly, derived from one or more careers, or both. A grade is a value on the record; the record itself is not a score. Every grade and benchmark is a resolved rung ( { id, grade, label } ), never a bare integer. ​ Attributes Field Type Description id string The skill id name / description / isCertification The skill selfGrade rung | null The person’s own grade selfYearsOfExperience number | null Self-reported managerGrade rung | null The manager’s grade managerYearsOfExperience number | null Manager-reported managerGradeUpdatedAt / managerGradeUpdatedBy string | null, { id, name } | null When the manager grade last changed and who changed it benchmark.effective / benchmark.source rung | null, manager | level | career | null The single resolved benchmark and which value won benchmark.manager rung | null A manager-set benchmark for this person on this skill benchmark.careers[] Per career deriving the skill: career , level , effective , effectiveSource , the career, its skill and the assignment’s level notApplicable boolean Excluded from the profile; setting it clears the manager grade focus.employee / focus.manager boolean Two independent development-focus flags origin.direct boolean Attached to the profile in its own right origin.careers[] { careerId, careerName, careerSkillId } The careers deriving the skill, and the career skill each derives through The benchmark rule is the app’s, written down: most specific wins — the manager benchmark, then the assignment level’s benchmark (whenever the assignment has a level, even if that level sets none), then the career’s benchmark. Across several careers the highest career-derived effective value is published as benchmark.effective ; the contributing values are all present so a caller can see which one won. { "id" : "77" , "name" : "Forklift Operation" , "description" : null , "isCertification" : false , "selfGrade" : { "id" : "2" , "grade" : 2 , "label" : "Competent" }, "selfYearsOfExperience" : 3 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 4 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1041" , "name" : "Sam Ortega" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "career" , "manager" : null , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : null , "levelName" : null , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : null , "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "career" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [{ "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" }] } } ​ Operations ​ A person’s skills Operation Method and path Requires scope List a person’s skills GET /api/v1/people/{personId}/skills skills:read Get one of a person’s skills GET /api/v1/people/{personId}/skills/{skillId} skills:read List person skills for a population GET /api/v1/person-skills?scope=company|team|org&subject=… proficiency:read Skill matrix — people with a skill, and their grades GET /api/v1/skills/{id}/matrix proficiency:read personId is an email or an opaque id. The list returns every skill on the profile — attached directly or derived from a career — with the full object above. The population read is one operation over the app’s three reads: scope=company needs an administrator-level acting person; scope=team and scope=org read the team or organisation branch of the manager named by subject , who must be the acting person or within their span. Rows are one per person per skill (per career when graded through one) and are filterable by skillName , skillId , firstName , lastName . ​ Grading Operation Method and path Requires scope Set the self grade PUT /api/v1/people/{personId}/skills/{skillId}/self-grade proficiency:write Set the manager grade PUT /api/v1/people/{personId}/skills/{skillId}/manager-grade proficiency:write Grade a person across a career POST /api/v1/people/{personId}/careers/{careerId}/grades proficiency:write Set a per-person benchmark PUT /api/v1/people/{personId}/skills/{skillId}/benchmark proficiency:write Mark a skill not applicable PUT /api/v1/people/{personId}/skills/{skillId}/not-applicable proficiency:write Flag a skill as a focus PUT /api/v1/people/{personId}/skills/{skillId}/focus proficiency:write Remove a skill from a person DELETE /api/v1/people/{personId}/skills/{skillId}?attachment=… proficiency:write Grades take { "gradeId": "3", "yearsOfExperience": 4, "comment": "…" } ; gradeId must be a rung of the company grading scale (a field-level validation error otherwise). Only the person may set their self grade ; the manager grade needs the acting person to manage the subject or to be an administrator. Grade across a career takes { "grades": [{ "skillId", "managerGradeId"?, "managerYearsOfExperience"?, "selfGradeId"?, "selfYearsOfExperience"? }] } and applies to skills the career requires for that person; any other skill is 422 unprocessable . Grading attaches the skill directly as well , as the app does: after a grade, origin.direct is true even for a skill that arrived through a career, and the career derivation is kept alongside it. Benchmark takes { "gradeId": "4" } or { "gradeId": null } to clear — never a zero. Not applicable takes { "notApplicable": true } and clears the person’s manager grade : this is not a display flag, it discards data. Focus takes { "employee": true } (the person only) and/or { "manager": true } ; clearing the manager flag also clears the employee flag, as in --- ## The Skill object URL: https://help.skillsdb.com/api-docs/resources/skill Quick Summary: A skill is a company-level definition. Its configuration on a career (benchmark, Required status, per-level activation) belongs to the Career resource, not here. ​ Attributes Field Type Description id string Opaque skill id name string Skill name description string | null Description isCertification boolean Whether the skill is a certification. Read-only — creates never set it isArchived boolean Whether the skill is archived. Archived skills leave the default library listing but keep their history — see Retirement and delete { "id" : "63" , "name" : "Welding" , "description" : "MIG and TIG welding." , "isCertification" : false , "isArchived" : false } List entries ( GET /api/v1/skills ) additionally carry a usage object: Field Type Description usage.careers array References { id, name } to every career that includes the skill — attached directly or under a section, Required or not usage.peopleCount integer How many active people hold the skill, directly or through a career that includes it usage.trainingDatesEnabled boolean Whether any career including the skill has training dates enabled ​ Versions and activity GET /api/v1/skills/{id}/versions — every name/description snapshot, who edited it, when, an optional change note, and whether it is the baseline entry written when the skill was created. GET /api/v1/skills/{id}/activity — a version log, not a change feed . Exactly three event types are ever emitted: baseline (skill created), version_created (name or description changed, linked to its version entry via versionId ), and renew_training (with affectedUserCount and renewalOption ). A request approval, a career adding or removing the skill, and a benchmark or Required-status change produce no entry here — unlike the career activity feed , which records roughly forty event types. ​ Retirement and delete Two lanes, both reversible in spirit — prefer archive: POST /api/v1/skills/{id}/archive and POST /api/v1/skills/{id}/unarchive — the retirement path. An archived skill leaves the default library listing but keeps every grade, training and history row, stays readable by id, and can be brought back. DELETE /api/v1/skills/{id} — a soft delete: career attachments, grades and history are preserved as historic data, but the skill leaves every listing, filter and read. When the skill is attached to careers or held by people the call refuses with a 409 conflict carrying dependencies counts; retry with ?confirm=true to proceed. A skill nothing references (a mistyped creation, say) deletes without ceremony. A deleted skill answers 404 on every read from that point on. --- ## The Skill Request object URL: https://help.skillsdb.com/api-docs/resources/skill-request Quick Summary: A skill request proposes a name and description for a new library skill. Approving it creates the skill and assigns it to the requester; rejecting it records the decision. Either way the decision is final — a decided request returns a conflict if decided again. ​ Attributes Field Type Description id string Opaque request id name string | null The requested skill name description string | null The requested description status string pending , approved or rejected requestedById string | null Person id who requested the skill requestedAt string | null When it was requested (ISO 8601 UTC) reviewedById string | null Person id who decided it, once decided decidedAt string | null When it was decided reviewNotes string | null The reason given when the request was decided, if any { "id" : "17" , "name" : "Hydraulic Systems" , "description" : "Maintenance of hydraulic power units." , "status" : "approved" , "requestedById" : "91" , "requestedAt" : "2026-03-01T09:00:00.000Z" , "reviewedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reviewNotes" : "Approved for the fabrication track." } ​ Workflow POST /api/v1/skill-requests submits a proposed name and description. The request starts pending . POST /api/v1/skill-requests/{id}/approve accepts it, with an optional reason . Approving creates the skill in the library and assigns it to the requester. POST /api/v1/skill-requests/{id}/reject declines it, with an optional reason — the same field name every rejection in this API takes. ( notes is accepted as a deprecated alias.) Filter the list with status=pending|approved|rejected . The underlying record also carries a category and a free-text category suggestion; both are deprecated and neither is exposed. --- ## The Survey object URL: https://help.skillsdb.com/api-docs/resources/survey Quick Summary: A survey is one run of a survey template against a population of people. A template with its questions can be created over the API ( POST /api/v1/survey-templates ) or in the app; the API creates runs from a template version, manages who receives them, drives the lifecycle, and reads the results. ​ Attributes Field Type Description id string Opaque survey id name string Display name description string | null Description status enum draft , scheduled , launched , ended , cancelled templateVersion object | null The pinned template version: { id, name, version, templateId, templateName } . A run is pinned to one version — later template edits never change a running survey toAllPeople boolean Whether the population is everyone in the company scheduledFor string | null Future launch time, when scheduled launchedAt string | null When it launched dueDate string | null Responses due by lastNudgeSentAt string | null When participants were last reminded participants object Counts by participation status: { notStarted, inProgress, completed } createdById string | null Person who created the run createdAt / updatedAt string | null Timestamps (UTC) ​ Templates A run points at a template version , so a brand-new company needs a template before its first survey. Operation Method and path Scope List templates GET /api/v1/survey-templates surveys:read Create a template with its questions POST /api/v1/survey-templates surveys:write Read a template and its questions GET /api/v1/survey-templates/{id} surveys:read Create takes the template’s name , an optional description and visibility ( visible_to_all — the default — or private ), and its questions in order. Each question is { name, text, type, responseRequired?, allowsMultipleResponses?, options? } ; type is one of rating , text , multiple_choice , drop_down . Choice questions need at least two options ( { "label": "HQ" } ); rating and text questions take none. The response carries latestVersion.id — the value to send as templateVersionId when creating a survey — and the questions in the same shape GET /surveys/{id}/questions returns. The list shows each template’s newest version with questions: null ; the single read includes them. Editing a template (which cuts a new version) is done in the app. ​ Lifecycle draft → scheduled → launched → ended , with cancelled reachable before ending. The transitions are explicit operations, and an out-of-order call answers a 409 conflict describing the required state: POST /api/v1/surveys/{id}/schedule — set a future launch time on a draft; re-scheduling is allowed while the current time is still more than an hour away. POST /api/v1/surveys/{id}/launch — launch now: the population is materialised into participants and notified. A survey nobody would receive is a 409. POST /api/v1/surveys/{id}/end — close a launched survey to further responses. POST /api/v1/surveys/{id}/cancel — cancel a run. POST /api/v1/surveys/{id}/nudge — remind everyone who has not completed; answers 202 , the reminders send asynchronously. ​ Population The population is defined while the survey is a draft (or still more than an hour from a scheduled launch), and materialised at launch: GET /api/v1/surveys/{id}/scope — the definition: toAllPeople , the nine org-dimension id lists, personIds (named individuals), excludedPersonIds . State ids appear read-only. PUT /api/v1/surveys/{id}/scope — replace the definition. Turning toAllPeople off and naming people scopes the run to exactly those individuals. POST /api/v1/surveys/{id}/exclusions / DELETE …/exclusions — exclude named individuals from any population, or lift the exclusion. Refused once launched. People in write bodies are emails ; every response carries the opaque personId and the email. ​ Reading a run GET /api/v1/surveys — paginated, filterable by status (public values above), name and dates. GET /api/v1/surveys/{id} — one run. GET /api/v1/surveys/{id}/questions — the pinned question set: { id, name, text, description, version, type, responseRequired, allowsMultipleResponses, options } with type one of multiple_choice , drop_down , rating , text , document_upload , certification_update . GET /api/v1/surveys/{id}/people — participants with person {id, name, email} , status ( assigned , in_progress , completed , archived ), how each was included ( all_people , org_schema , manual ), and timestamps. GET …/people/{person} reads one participation; the person slot takes an email or the opaque id. Responses live on the Survey Response page. ​ Scopes Reads require surveys:read ; every write requires surveys:write . Employee-bound credentials are read-only apart from submitting their own responses. --- ## The Survey Response object URL: https://help.skillsdb.com/api-docs/resources/survey-response Quick Summary: A response is one person’s answer to one question of a launched survey. The answer is a typed object — its shape follows the question type — and every response carries a reference to the exact question version it answered, so results stay interpretable after a template evolves. ​ Attributes Field Type Description id string Opaque response id personId string Who answered question object The question version answered: { id, questionVersionId, name, text, version, type } answer object The typed answer — see below createdAt / updatedAt string | null Timestamps (UTC) ​ The answer object Field Type Description kind enum text , rating , file , choices , certification , empty text string | null Text answers rating number | null Rating answers fileName string | null Document-upload answers options array Chosen options for choice questions: { id, name } certificationCount integer Certifications attached by a certification-update answer Exactly the members matching kind are populated; the rest are explicit nulls / empties. ​ Operations Operation Scope Notes GET /api/v1/surveys/{id}/responses surveys:read Every response collected by the run, paginated GET /api/v1/surveys/{id}/people/{person}/responses surveys:read One participant’s responses; the person slot takes an email or the opaque id POST /api/v1/surveys/{id}/people/{person}/responses surveys:write Submit an answer — self only : the credential’s acting person must be the participant, anyone else is a 403 . The survey must be launched — an ended, cancelled or draft run answers a 409 GET /api/v1/surveys/{id}/responses/{responseId}/download-url surveys:read A time-limited download link for a file answer ​ Submitting The body names the question ( questionId from the survey’s question set ) plus the answer member matching its type — text , rating , or a file name. A document-upload answer is two steps : the response is created and the result carries a time-limited uploadUrl ; PUT the file bytes there. Re-submitting the same question updates the answer while the run is launched. Answering moves the participation status from assigned to in_progress ; completing every required question marks it completed . --- ## The Training Record object URL: https://help.skillsdb.com/api-docs/resources/training Quick Summary: A training belongs to a person skill — the skill must already be on the person’s profile before a training can be recorded. Approval is a full request-and-decide workflow with delegation; renewal supersedes records without deleting them. ​ Attributes Field Type Description id string Opaque training record id person / skill object References { id, name } trainingDate string | null When the training took place trainer string | null Free text, never a person reference. Who trained is unvalidated; who approved is the person in decision ; who may train is a trainer-designating flag status string See the status table below isNotApplicable boolean Excluded without being deleted evidenceNote string | null The text half of evidence; files come through /trainings/{id}/evidence as time-limited links expiresAt / isExpired — Expiry is a date ; the expired state is derived from it, never a lifecycle status the API sets skillVersionId string | null The skill version the training was completed against — what makes a superseded record identifiably stale requestedById / requestedAt / delegatedApproverId — The submission side. The ids are opaque response ids — requests name a delegate by email ( delegatedApproverEmail ) decision object | null { outcome, decidedById, decidedAt, reason } once decided isSuperseded boolean True when the record was replaced by a renewal and lives in training history ​ Statuses Status Written by awaiting_approval , approved , rejected , cancelled Application flow and this API needs_reapproval Renewal (the internal name “Update” gives no hint of that) expired , pending , submitted Only the CSV history importer — reads can return them, but no API write produces or transitions them ​ Recording POST /trainings names the person by email address : { "email" : "ada@example.com" , "skillId" : "63" , "delegatedApproverEmail" : "dana@example.com" } The optional delegatedApproverEmail routes the approval to a named person. Reads scope to one person the same way: GET /trainings?email=ada@example.com and GET /training-approvals?email= take the email, and /people/{personId}/... path slots accept the email (or the opaque id from any response). ​ Approval GET /training-approvals?status= covers every decidable state, not just the pending queue. GET /trainings/{id}/potential-approvers unions three unrelated authorities: global-admin/full-access users, the submitter’s entire chain of command, and holders of a trainer-designating skill flag ( expertsOnly=true returns just the flag holders). GET /people/{id}/approval-activity lists everything a person decided; GET /people/{id}/approval-requests is the other side. Entitlement is point-in-time and not retained. The decision records who decided, never under which authority — flags get removed, reporting lines change. Whether an approval came from a trainer flag or the chain of command cannot be reconstructed later. ​ Renewal supersedes, it does not delete POST /skills/{id}/renew-training marks affected trainings needs_reapproval across everyone holding the skill — a fan-out counted against the bulk rate-limit bucket. Preview first with GET /skills/{id}/renew-training/preview . Superseded records stay readable through GET /people/{personId}/skills/{skillId}/training-log , the only read that spans live and superseded records together. --- ## Authentication URL: https://help.skillsdb.com/api-docs/rest/authentication Quick Summary: Every request carries Authorization: Bearer sdb_live_... . Keys are created by administrators, scoped per resource, bound to an acting person, rotated with an overlap window, and revoked instantly. ​ The key A key looks like sdb_live_ followed by 32 random characters. The prefix identifies the environment that issued the key — production uses sdb_live_ , a sandbox or staging environment issues its own (for example sdb_test_ ). Only the secret’s length and opacity are guaranteed, so never hard-code or validate the prefix in your client. Send the key on every request: curl https://prod.skillsdbnext.com/api/v1/careers \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" Only the key first characters and last four are ever displayed again — the full key is shown once at creation and only a one-way hash is stored. ​ Scopes and the acting person A key carries scopes in resource:action form — careers:read , careers:write , and so on. :write never implies :read . Independently, every key is bound to an acting person : the API’s effective permission is always the intersection of the key scopes and what that person may do in the app. A 403 tells you which of the two blocked the call by its type : insufficient-scope means grant the key a scope; insufficient-permissions means the acting person cannot do this in the app, and no scope will help. Scope changes take effect on the very next request — nothing is cached. How people are identified: the person identifier on this API is the email address — in bodies, query filters, and /people/{id} -style path slots (which also accept the opaque id from any response). Every lookup is bounded by the key’s company: an email held by another company returns the same 404 as one that does not exist, so the API never confirms an address elsewhere. Duplicate case-variants of one address in your own data answer 409 instead of a silent pick — see Getting Started . ​ Scope reference Every endpoint’s reference page states the scope it needs on its Requires scope line. /ping is the one scope-free endpoint — any valid key can call it. Remember the intersection rule above: a scope grants nothing the acting person cannot already do in the app — it only ever narrows. Scope Grants skills:read Read skills, their versions and activity, and skill requests skills:write Create and update skills; create and decide skill requests people:read Read people, their org schema memberships and the reporting structure people:write Create and update people (bulk provisioning included), manage their org schema memberships, manager, email, access level and lifecycle careers:read Read careers, career types, levels, assignments, distributions, activity and the grading scale careers:write Author careers and their structure; assign and unassign people training:read Read training records and approval activity training:write Create and update training records; record approval decisions flags:read Read people flags and skill flags, and who holds them flags:write Create flags; apply and remove them org:read Read the org structure dimensions org:write Create and update org structure entries learning:read Read learning plans, the training library (learning items, reference lists) and learning suggestions learning:write Assign learnings and update learning plan entries; maintain the training library and decide suggestions certifications:read Read the certification library and types, a person’s certifications, their history and attachments, and coverage reporting certifications:write Maintain the certification library and types; record, submit, approve, deny, renew and unassign a person’s certifications assessments:read Read assessment cycles, participation, assessment grades and reports assessments:write Administer assessment cycles: create, schedule, scope, exclude, nudge, start and end proficiency:read Read person skill grades, benchmarks, focus and origin across a population; grade reporting proficiency:write Grade people on skills, set per-person benchmarks, mark skills not applicable or focused surveys:read Read survey runs, participation, responses and the frozen question set behind them surveys:write Administer survey runs and their population; submit responses labels:read Read labels, the label tree, and which labels an object carries labels:write Create, update, reorder, reparent and delete labels; attach and detach them ​ Rotation Rotating a key issues a replacement (same scopes, same acting person, new secret) while the old key keeps working for an overlap window (24 hours by default). Deploy the new key at your leisure inside the window; the old key stops working when it ends. ​ Revocation Revoking a key stops it immediately — the key status is checked live on every request. ​ What a 401 means Any authentication failure returns the same generic invalid-credential problem — the API never reveals whether a key exists, expired, was revoked, or was never valid. --- ## Client Libraries URL: https://help.skillsdb.com/api-docs/rest/client-libraries Quick Summary: SkillsDB publishes no official SDKs today. The OpenAPI 3 document is built for client generation — download it from /api/v1/openapi.json and generate a typed client with the tool of your choice. ​ The contract is the SDK The machine-readable contract behind these docs is an OpenAPI 3 document, downloadable without authentication: curl https://prod.skillsdbnext.com/api/v1/openapi.json -o skillsdb.openapi.json It is client-generation-grade: every operation has a stable operationId (the method names a generator produces), and CI treats removing or renaming one as a breaking change that blocks the merge — inside v1 the contract only ever changes additively. A client you generate today keeps compiling against tomorrow’s document. ​ Generating a typed client Any OpenAPI 3 generator works. For TypeScript, openapi-typescript produces types with no runtime: npx openapi-typescript skillsdb.openapi.json -o skillsdb.d.ts For a full client in most languages, openapi-generator : npx @openapitools/openapi-generator-cli generate \ -i skillsdb.openapi.json -g typescript-fetch -o ./skillsdb-client Point the generated client’s base URL at your environment and set the Authorization: Bearer sdb_live_YOUR_KEY_HERE header — see Authentication . Tip: Prefer exploring by hand first? The Postman collection is generated from the same contract. --- ## Errors URL: https://help.skillsdb.com/api-docs/rest/errors Quick Summary: Every error is application/problem+json with a type URL that resolves to the error catalogue . Log the requestId from every response — it is the tracing handle for support. ​ The shape { "type" : "https://help.skillsdb.com/api-docs/errors/insufficient-scope" , "title" : "Insufficient scope" , "status" : 403 , "detail" : "This credential does not have the 'careers:write' scope" , "instance" : "/api/v1/careers" , "requestId" : "01a01ed7-a41b-7183-a017-be375fd23874" } type — a URL naming the error class; open it for causes and fixes. detail — human-readable specifics of this occurrence. instance — the path that produced it. requestId — also sent as the X-Request-Id header on every response, success or failure. errors[] — on validation failures, the per-field breakdown. Some errors add extension members (for example a guarded delete dependencies counts). ​ Status codes at a glance Status Types 400 validation-error 401 invalid-credential 403 insufficient-scope — the key lacks the scope 403 insufficient-permissions — the acting person may not do this 404 not-found 409 conflict , idempotency-key-reused 410 version-gone 422 unprocessable 429 rate-limit-exceeded 500 internal-error --- ## Filtering URL: https://help.skillsdb.com/api-docs/rest/filtering Quick Summary: Filter collections with filter[field][op]=value . Each endpoint documents which fields are filterable; anything else is rejected with a 400 naming the field. ​ Syntax # careers whose name contains "engineer" curl "https://prod.skillsdbnext.com/api/v1/careers?filter[name][like]=%25engineer%25" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" # careers of one career type (by type name) curl "https://prod.skillsdbnext.com/api/v1/careers?filter[careerType][eq]=Job%20Role" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" %25 is a URL-encoded % — the SQL-style wildcard for like . ​ Operators Operator Meaning eq / neq equals / not equals gt gte lt lte comparisons in / nin in / not in a comma-separated list like / nlike pattern match with % wildcards isnull true or false ​ Whitelists Filterable fields are declared per endpoint in the reference. Unknown fields — including any attempt to filter by companyId — return a 400 with code not_filterable . Your key company boundary is enforced by the server on every query; it is never a parameter. --- ## Getting Started URL: https://help.skillsdb.com/api-docs/rest/getting-started Quick Summary: Create an API key in Settings → API Credentials , send it as a Bearer token, call /api/v1/ping to prove the connection, then make your first real call. ​ 1. Create an API key A company administrator creates keys under Settings → API Credentials : give it a name, pick its scopes (for example careers:read ), and choose the acting person — the API can never do more than that person could do in the app. The key is shown exactly once at creation. Copy it immediately — only a one-way hash is stored, and a lost key can only be replaced, never recovered. ​ 2. Prove the connection curl https://prod.skillsdbnext.com/api/v1/ping \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" { "data" : { "status" : "ok" , "version" : "v1" , "time" : "2026-08-20T11:00:00.000Z" } } /ping requires a valid key but no scope — it is the scope-free connectivity check. ​ 3. Make your first real call curl "https://prod.skillsdbnext.com/api/v1/careers?limit=5" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" { "data" : [ { "id" : "18" , "name" : "Maintenance Technician" , "careerType" : { "id" : "3" , "name" : "Job Role" }, "levelCount" : 3 , "..." : "..." } ], "meta" : { "total" : 42 , "limit" : 5 , "offset" : 0 } } ​ The conventions, in one paragraph Every response is JSON with camelCase fields. Collections are { data: [...], meta: { total, limit, offset } } ; single resources are { data: {...} } . Ids are opaque strings. Timestamps are ISO 8601 UTC with a Z . Nullable fields are always present with an explicit null . Errors are RFC 9457 problem+json — see the error catalogue . The machine-readable contract is at /api/v1/openapi.json (no authentication needed). ​ How people are identified The person identifier is the email address . Request bodies and query filters take emails only ( email , emails , managerEmail , delegatedApproverEmail , ?email= ), and path slots like /people/{id} take the email as the primary form — the opaque person id from any response also works there, and the two forms never collide (ids are all digits, an email always contains @ ). Responses keep opaque ids. Resolution is bounded by your company: an email held by another company answers the same 404 as one that does not exist. One edge — if your data holds case- or whitespace-variant duplicates of the same address, the API refuses with a 409 rather than pick a record; resolve the duplicates or use the opaque id. ​ Writes can notify people Some write operations notify affected people by email as a side effect — assigning learning emails the assignee, launching a survey notifies its participants, submitting a training for approval notifies approvers. The API follows the company’s notification configuration exactly as the app does : whatever your administrators have enabled in SkillsDB applies to API-originated changes too, and there is no per-request switch to force or suppress an email in v1. If a bulk sync should run silently, adjust the company’s notification settings for that window rather than expecting a request flag. ​ Explore with Postman A ready-made Postman collection is generated from the same contract. Import it, open the collection’s Variables tab, paste your key into apiKey and point baseUrl at your environment — every request inherits the collection-level authentication and common headers, so nothing needs configuring per request. Write requests carry an optional, one-click Idempotency-Key header prefilled with a GUID, and request bodies come prefilled with working examples. ​ Where next Authentication — key lifecycle, rotation, revocation Pagination , Filtering , Sorting Idempotency — safe retries for writes Rate limits The endpoint reference in this section’s sidebar — one section per resource, one page per operation --- ## Idempotency URL: https://help.skillsdb.com/api-docs/rest/idempotency Quick Summary: Send a unique Idempotency-Key header on any write. Retrying with the same key and the same body replays the original response instead of performing the operation twice. ​ The contract curl -X POST "https://prod.skillsdbnext.com/api/v1/careers" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" \ -H "Idempotency-Key: 0e8a7d1c-4f4b-4e9c-a2ce-1b6f2f6f9d55" \ -H "Content-Type: application/json" \ -d '{"name":"Maintenance Technician"}' First execution stores the successful response for 24 hours. A retry (same key, same method, path and body) replays it verbatim, with the header Idempotency-Replayed: true , executing nothing. Same key, different content → 409 idempotency-key-reused . Two concurrent duplicates → exactly one executes; the other briefly waits, then replays or returns a 409 conflict asking you to retry shortly. Errors are never replayed — a failed request releases the key so the same key can retry. ​ Rules of thumb Generate a UUID per logical operation. Reuse it only for retries of that exact request. The header is optional — without it every request executes. --- ## Pagination URL: https://help.skillsdb.com/api-docs/rest/pagination Quick Summary: Collections take limit (default 50, max 200) and offset (max 10,000). Out-of-range values are rejected with a 400 , never silently clamped. curl "https://prod.skillsdbnext.com/api/v1/careers?limit=50&offset=100" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" Every collection response carries the paging state back to you: { "data" : [ "..." ], "meta" : { "total" : 342 , "limit" : 50 , "offset" : 100 } } Iterate until offset + limit >= total . If you find yourself paging past the 10,000-offset cap, narrow the result set with filters instead — deep offset pagination is slow for everyone. Sub-resource lists that are naturally complete (a career’s levels, sections, skills) return the full set in one response with meta.total equal to the length. --- ## Polling for Changes URL: https://help.skillsdb.com/api-docs/rest/polling Quick Summary: The v1 API does not deliver webhooks. Detect changes by polling the activity feeds on a schedule, filtered by date, and send an Idempotency-Key on any write your poller triggers. ​ No webhooks There is no webhook or event-subscription mechanism in v1 — SkillsDB never calls your systems. If your integration needs to react to changes, poll for them. ​ Polling the activity feeds Two resources expose an activity feed: Feed Endpoint Scope Career activity GET /api/v1/careers/{id}/activity careers:read Skill activity GET /api/v1/skills/{id}/activity skills:read The career feed accepts from and to (ISO 8601 UTC) plus event and performedBy filters. Poll it by remembering when you last polled and asking only for what is new: curl "https://prod.skillsdbnext.com/api/v1/careers/318/activity?from=2026-08-30T00:00:00Z" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" Process the entries, store the poll time, and use it as the next from . Overlap the windows slightly and deduplicate on the entry id rather than trusting an exact boundary. The skill feed is a version log ( baseline , version_created , renew_training ) with pagination only — no date filter. Each entry carries performedAt ; page through and stop when you reach entries you have already seen. ​ Keep the poller polite Polls are GETs, counted against the reads bucket — 1,000 per hour per key. Watch RateLimit-Remaining and size your interval so a full sweep fits comfortably. If a poll result triggers a write back into SkillsDB, send an Idempotency-Key from day one — a poller that crashes mid-run and restarts will otherwise perform its writes twice. --- ## Rate Limits URL: https://help.skillsdb.com/api-docs/rest/rate-limits Quick Summary: Requests are counted per key, per hour, in three buckets: reads, writes and bulk. Every response carries RateLimit-* headers so you always know where you stand. Current status: limits are measured but not yet enforced. The numbers below are provisional; they will be finalized from real usage data and announced to all credential holders before enforcement is switched on. Build your integration against the headers now and enforcement will never surprise you. ​ Buckets and provisional allowances Bucket Counts Provisional allowance reads Every GET 1,000 / hour writes POST, PUT, PATCH, DELETE 300 / hour bulk Bulk endpoints 20 / hour A per-key allowance override is possible for legitimate high-volume integrations — talk to your SkillsDB contact. ​ The headers Header Meaning RateLimit-Limit This bucket allowance RateLimit-Remaining Requests left in the current window RateLimit-Reset Seconds until the window resets Once enforcement is on, exceeding an allowance returns 429 rate-limit-exceeded with Retry-After . Windows are fixed UTC hours. --- ## Sorting URL: https://help.skillsdb.com/api-docs/rest/sorting Quick Summary: Sort with sort=field (ascending) or sort=-field (descending), comma-separated for multiple keys. Sortable fields are whitelisted per endpoint. curl "https://prod.skillsdbnext.com/api/v1/careers?sort=name" \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" A field outside the endpoint whitelist returns a 400 with code not_sortable . Endpoints with a natural order (a career’s levels, sections and skills follow their configured positions; the activity feed is newest-first) ignore sort and document that in the reference. --- ## Testing Your Integration URL: https://help.skillsdb.com/api-docs/rest/testing Quick Summary: There is no test mode and no test-key prefix. Develop against the staging server with a key created in a staging tenant, prove the connection with /ping , and hold write scopes back until you need them. ​ One key format, two environments Every key uses the same sdb_live_ prefix — a key is “test” or “production” only by virtue of which tenant issued it . A key issued in a production tenant performs real operations on real data; nothing about the key stops you. The safe setup is a dedicated staging tenant: ask your SkillsDB contact for one, then create an API key there under Settings → API Credentials exactly as you would in production. The staging server is part of the OpenAPI document : curl https://staging.skillsdbnext.com/api/v1/ping \ -H "Authorization: Bearer sdb_live_YOUR_KEY_HERE" /ping needs a valid key but no scope — it is the first call to make in any new environment. ​ Habits that pay off Start with read-only scopes. Grant careers:read , people:read and friends while you develop; add :write scopes only when you start writing. :write never implies :read , so nothing is lost by starting narrow. Send Idempotency-Key from day one. Retry behavior is part of your integration, not a production afterthought. Build against the RateLimit-* headers now, while limits are measured but not enforced. Warning: Staging sends real email. A write that produces notifications — assigning a career, granting a learning — will email the affected people in the staging tenant. Seed staging with addresses you control, not your workforce’s. --- ## Versioning URL: https://help.skillsdb.com/api-docs/rest/versioning Quick Summary: The version is in the URL — /api/v1/... . Inside a major version we only ever add ; anything breaking waits for the next major, with a long, loudly-announced migration window. ​ What will never change inside v1 Existing routes, parameters and response fields keep their names and types. Optional things stay optional; enum values are never removed or renamed. Status codes and error types for existing behaviour stay put. ​ What may appear without notice New endpoints, new optional parameters, new response fields, new enum values, new error detail text. Build tolerant clients: ignore fields you do not recognize. ​ How a version retires See the versioning & deprecation policy — deprecation headers first, a published sunset date, then 410 version-gone after the sunset. The machine-readable contract for the current version is always at /api/v1/openapi.json . --- ## Versioning & Deprecation Policy URL: https://help.skillsdb.com/api-docs/rest/versioning-policy Quick Summary: Majors are URL-versioned. Inside a major, changes are additive-only. A retiring major gets a written notice period, machine-readable deprecation headers on every response, and a hard sunset date — after which it answers 410. The support and notice windows below are pending final Product sign-off and will be confirmed before v1 general availability. ​ The policy Commitment Rule Version scheme Major version in the URL ( /api/v1/ ). No date-based or header-based versioning. Inside a major Additive-only. Adding endpoints, optional request fields, response fields and enum values is allowed at any time. Breaking change definition Removing or renaming a path, parameter or field; changing a type; narrowing an enum; making something optional required; changing a status code; renaming an operation id. Support window A deprecated major keeps working for 12 months after its successor ships (pending sign-off) . Notice period Deprecation is announced at least 6 months before sunset (pending sign-off) . Machine-readable signals Every response of a deprecated version carries Deprecation (RFC 9745), Sunset (RFC 8594) and Link rel="deprecation" headers. After sunset Every route of the version returns 410 version-gone with a migration link. Rate limit changes Allowance reductions are announced to credential holders with lead time; increases may happen at any time. ​ What you should build Log a warning whenever a response carries a Deprecation header. That single line of client code converts every future migration from a surprise into a scheduled task. --- ## Sorting URL: https://help.skillsdb.com/api-docs/sorting Quick Summary: Use the orderBy parameter in SkillsDB GraphQL queries to sort results in ascending ( ASC ) or descending ( DESC ) order by any supported field. In most query operations, we provide the ability to sort the result set using the orderBy input parameter. For example: query getDomains { getDomains ( input : { orderBy : { DomainName : ASC } }) { count data { DomainId DomainName } } } In this query, we are asking for the domains but they need to be sorted in ascending order based on the DomainName . The other value allowed is of course DESC : query getDomains { getDomains ( input : { orderBy : { DomainName : DESC } }) { count data { DomainId DomainName } } } ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## List identity provider events URL: https://help.skillsdb.com/api-reference/activity/list-identity-provider-events List identity provider events cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/identity-provider-events \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/identity-provider-events" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/identity-provider-events', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/identity-provider-events", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/identity-provider-events" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/identity-provider-events") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/identity-provider-events") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "event" : "career_updated" , "description" : "Career renamed" , "performedById" : "88" , "performedAt" : "2026-03-02T14:00:00.000Z" , "oldValue" : "Manager" , "newValue" : "Director" , "payloadSummary" : "displayName: Jane D." , "source" : "scim" , "externalMemberId" : "member-abc123" , "relatedPersonId" : "91" , "relatedPersonName" : "Jane Doe" , "relatedGroupId" : "412" , "relatedGroupName" : "Engineering" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / identity-provider-events Try it List identity provider events cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/identity-provider-events \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/identity-provider-events" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/identity-provider-events', options) .then(res => res.json()) .then(res => --- ## Active assessment counts for the acting person URL: https://help.skillsdb.com/api-reference/assessment/active-assessment-counts-for-the-acting-person Active assessment counts for the acting person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/active-counts \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/active-counts" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/active-counts', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/active-counts", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/active-counts" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/active-counts") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/active-counts") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "self" : 1 , "team" : 6 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / active-counts Try it Active assessment counts for the acting person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/active-counts \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/active-counts" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/active-counts', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/active-counts", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer < --- ## Assessment report URL: https://help.skillsdb.com/api-reference/assessment/assessment-report Assessment report cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/report \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/report" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/report', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/report", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/report" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/report") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/report") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "manager" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "status" : "to_do" , "completedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" , "department" : "Operations" , "jobTitle" : "Technician" , "peopleType" : "Full-time" , "directReportsAssigned" : 12 , "directReportsCompleted" : 4 , "excludedFromAssessment" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / report Try it Assessment report cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/report \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/report" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/report', options) .then(res --- ## Assessment skills matrix URL: https://help.skillsdb.com/api-reference/assessment/assessment-skills-matrix Assessment skills matrix cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "section" : { "id" : "5" , "name" : "Safety" }, "level" : "Level 2" , "selfGrade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "managerGrade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true } } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / skills-matrix Try it Assessment skills matrix cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/skills-matrix \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessmen --- ## Attach population selections URL: https://help.skillsdb.com/api-reference/assessment/attach-population-selections Attach population selections cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "businessUnitIds": [ "3" ], "divisionIds": [ "<string>" ], "countryIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "departmentIds": [ "12", "15" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope" payload = { "businessUnitIds": ["3"], "divisionIds": [""], "countryIds": [""], "businessRegionIds": [""], "cityIds": [""], "siteIds": [""], "departmentIds": ["12", "15"], "teamIds": [""], "shiftIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ businessUnitIds: ['3'], divisionIds: [''], countryIds: [''], businessRegionIds: [''], cityIds: [''], siteIds: [''], departmentIds: ['12', '15'], teamIds: [''], shiftIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'businessUnitIds' => [ '3' ], 'divisionIds' => [ '' ], 'countryIds' => [ '' ], 'businessRegionIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'departmentIds' => [ '12', '15' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope" payload := strings.NewReader("{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "12" , "15" ], " --- ## Completion report URL: https://help.skillsdb.com/api-reference/assessment/completion-report Completion report cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "manager" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "directReport" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "status" : "to_do" , "completedAt" : null , "department" : "Operations" , "jobTitle" : "Technician" , "managerExcluded" : false , "excludedFromAssessment" : false , "excludedFromDirectReports" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / completion-report Try it Completion report cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/completion-report" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/as --- ## Create an assessment URL: https://help.skillsdb.com/api-reference/assessment/create-an-assessment Create an assessment cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/assessments \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "title": "Q2 Skills Review", "description": "Annual proficiency check-in.", "managerGradesVisibleAt": "immediately", "allPeople": true, "scope": { "businessUnitIds": [ "3" ], "divisionIds": [ "<string>" ], "countryIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "departmentIds": [ "12", "15" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ] }, "peopleTypeIds": [ "<string>" ], "employeeDeadlineAt": "2026-03-31", "managerDeadlineAt": "2026-04-15" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments" payload = { "title": "Q2 Skills Review", "description": "Annual proficiency check-in.", "managerGradesVisibleAt": "immediately", "allPeople": True, "scope": { "businessUnitIds": ["3"], "divisionIds": [""], "countryIds": [""], "businessRegionIds": [""], "cityIds": [""], "siteIds": [""], "departmentIds": ["12", "15"], "teamIds": [""], "shiftIds": [""] }, "peopleTypeIds": [""], "employeeDeadlineAt": "2026-03-31", "managerDeadlineAt": "2026-04-15" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ title: 'Q2 Skills Review', description: 'Annual proficiency check-in.', managerGradesVisibleAt: 'immediately', allPeople: true, scope: { businessUnitIds: ['3'], divisionIds: [''], countryIds: [''], businessRegionIds: [''], cityIds: [''], siteIds: [''], departmentIds: ['12', '15'], teamIds: [''], shiftIds: [''] }, peopleTypeIds: [''], employeeDeadlineAt: '2026-03-31', managerDeadlineAt: '2026-04-15' }) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'title' => 'Q2 Skills Review', 'description' => 'Annual proficiency check-in.', 'managerGradesVisibleAt' => 'immediately', 'allPeople' => true, 'scope' => [ 'businessUnitIds' => [ '3' ], 'divisionIds' => [ '' ], 'countryIds' => [ '' ], 'businessRegionIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'departmentIds' => [ '12', '15' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ] ], 'peopleTypeIds' => [ '' ], 'employeeDeadlineAt' => '2026-03-31', 'managerDeadlineAt' => '2026-04-15' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments" payload := strings.NewReader("{\n \"title\": \"Q2 Skills Review\",\n \"description\": \"Annual proficiency check-in.\",\n \"managerGradesVisibleAt\": \"immediately\",\n \"allPeople\": true,\n \"scope\": {\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n },\n \"peopleTypeIds\": [\n \"\"\n ],\n \"employeeDeadlineAt\": \"2026-03-31\",\n \"managerDeadlineAt\": \"2026-04-15\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/assessments") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"title\": \"Q2 Skills Review\",\n \"description\": \"Annual proficiency check-in.\",\n \"managerGradesVisibleAt\": \"immediately\",\n \"allPeople\": true,\n \"scope\": {\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n },\n \"peopleTypeIds\": [\n \"\"\n ],\n \"employeeDeadlineAt\": \"2026-03-31\",\n \"managerDeadlineAt\": \"2026-04-15\"\n}") .asString(); require 'uri' require 'net/http' url --- ## Detach population selections URL: https://help.skillsdb.com/api-reference/assessment/detach-population-selections Detach population selections cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "businessUnitIds": [ "3" ], "divisionIds": [ "<string>" ], "countryIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "departmentIds": [ "12", "15" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope" payload = { "businessUnitIds": ["3"], "divisionIds": [""], "countryIds": [""], "businessRegionIds": [""], "cityIds": [""], "siteIds": [""], "departmentIds": ["12", "15"], "teamIds": [""], "shiftIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ businessUnitIds: ['3'], divisionIds: [''], countryIds: [''], businessRegionIds: [''], cityIds: [''], siteIds: [''], departmentIds: ['12', '15'], teamIds: [''], shiftIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'businessUnitIds' => [ '3' ], 'divisionIds' => [ '' ], 'countryIds' => [ '' ], 'businessRegionIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'departmentIds' => [ '12', '15' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope" payload := strings.NewReader("{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/scope") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"businessUnitIds\": [\n \"3\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"12\",\n \"15\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "1 --- ## End a track URL: https://help.skillsdb.com/api-reference/assessment/end-a-track End a track cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/end \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "track": "employee", "suppressEmails": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/end" payload = { "track": "employee", "suppressEmails": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({track: 'employee', suppressEmails: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/end', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/end", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'track' => 'employee', 'suppressEmails' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/end" payload := strings.NewReader("{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/assessments/{id}/end") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/end") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "12" , "15" ], "teamIds" : [], "shiftIds" : [], "peopleTypeIds" : [] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestI --- ## Exclude or re-include a person URL: https://help.skillsdb.com/api-reference/assessment/exclude-or-re-include-a-person Exclude or re-include a person cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "excludedFromAssessment": true, "excludedFromDirectReports": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion" payload = { "excludedFromAssessment": True, "excludedFromDirectReports": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({excludedFromAssessment: true, excludedFromDirectReports: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'excludedFromAssessment' => true, 'excludedFromDirectReports' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion" payload := strings.NewReader("{\n \"excludedFromAssessment\": true,\n \"excludedFromDirectReports\": false\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"excludedFromAssessment\": true,\n \"excludedFromDirectReports\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/exclusion") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"excludedFromAssessment\": true,\n \"excludedFromDirectReports\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "managerId" : "1001" , "status" : "to_do" , "tracks" : { "employee" : { "status" : "to_do" , "completedAt" : null , "completedById" : null }, "manager" : { "status" : "to_do" , "completedAt" : null , "completedById" : null } }, "completedAt" : null , "excludedFromAssessment" : false , "excludedFromDirectReports" : false , "includedAt" : "2026-02-20T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { --- ## Get a person's participation URL: https://help.skillsdb.com/api-reference/assessment/get-a-persons-participation Get a person's participation cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "managerId" : "1001" , "status" : "to_do" , "tracks" : { "employee" : { "status" : "to_do" , "completedAt" : null , "completedById" : null }, "manager" : { "status" : "to_do" , "completedAt" : null , "completedById" : null } }, "completedAt" : null , "excludedFromAssessment" : false , "excludedFromDirectReports" : false , "includedAt" : "2026-02-20T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / people / {personId} Try it Get a person's participation cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skill --- ## Get an assessment URL: https://help.skillsdb.com/api-reference/assessment/get-an-assessment Get an assessment cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "12" , "15" ], "teamIds" : [], "shiftIds" : [], "peopleTypeIds" : [] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} Try it Get an assessment cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id} \ --header 'Auth --- ## List a person's assessment grades URL: https://help.skillsdb.com/api-reference/assessment/list-a-persons-assessment-grades List a person's assessment grades cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people/{personId}/grades") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "section" : { "id" : "5" , "name" : "Safety" }, "career" : "Warehouse Operator" , "self" : { "grade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "yearsOfExperience" : 3 , "notes" : "Strong on the floor, needs the paperwork." , "gradedAt" : "2026-03-05T10:00:00.000Z" , "promoted" : false }, "manager" : { "grade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "yearsOfExperience" : 3 , "notes" : "Strong on the floor, needs the paperwork." , "gradedAt" : "2026-03-05T10:00:00.000Z" , "promoted" : false }, "managerGradesVisible" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "priorSelfGrade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "priorManagerGrade" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true }, "notApplicable" : false , "focus" : { "manager" : false , "employee" : true } } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-er --- ## List assessments URL: https://help.skillsdb.com/api-reference/assessment/list-assessments List assessments cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments Try it List assessments cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {meth --- ## List exclusions URL: https://help.skillsdb.com/api-reference/assessment/list-exclusions List exclusions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "person": { "id": "1042", "email": "ada@example.com", "firstName": "Ada", "lastName": "Lovelace" }, "managerId": "1001", "status": "to_do", "tracks": { "employee": { "status": "to_do", "completedAt": null, "completedById": null }, "manager": { "status": "to_do", "completedAt": null, "completedById": null } }, "completedAt": null, "excludedFromAssessment": false, "excludedFromDirectReports": false, "includedAt": "2026-02-20T09:00:00.000Z" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / exclusions Try it List exclusions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/exclusions', options) .then(res = --- ## List people in an assessment URL: https://help.skillsdb.com/api-reference/assessment/list-people-in-an-assessment List people in an assessment cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "email" : "ada@example.com" , "firstName" : "Ada" , "lastName" : "Lovelace" }, "managerId" : "1001" , "status" : "to_do" , "tracks" : { "employee" : { "status" : "to_do" , "completedAt" : null , "completedById" : null }, "manager" : { "status" : "to_do" , "completedAt" : null , "completedById" : null } }, "completedAt" : null , "excludedFromAssessment" : false , "excludedFromDirectReports" : false , "includedAt" : "2026-02-20T09:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / assessments / {id} / people Try it List people in an assessment cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/people', options) --- ## Nudge participants URL: https://help.skillsdb.com/api-reference/assessment/nudge-participants Nudge participants cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "target": "employee" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge" payload = { "target": "employee" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({target: 'employee'}) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'target' => 'employee' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge" payload := strings.NewReader("{\n \"target\": \"employee\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"target\": \"employee\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/nudge") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"target\": \"employee\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "target" : "employee" , "queued" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } --- ## Start a track URL: https://help.skillsdb.com/api-reference/assessment/start-a-track Start a track cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id}/start \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "track": "employee", "suppressEmails": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}/start" payload = { "track": "employee", "suppressEmails": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({track: 'employee', suppressEmails: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}/start', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}/start", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'track' => 'employee', 'suppressEmails' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}/start" payload := strings.NewReader("{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/assessments/{id}/start") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}/start") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"track\": \"employee\",\n \"suppressEmails\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "12" , "15" ], "teamIds" : [], "shiftIds" : [], "peopleTypeIds" : [] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/pe --- ## Update an assessment URL: https://help.skillsdb.com/api-reference/assessment/update-an-assessment Update an assessment cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/assessments/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "title": "Q2 Skills Review (final)", "description": "Updated brief.", "allPeople": false, "peopleTypeIds": [ "<string>" ], "employeeDeadlineAt": "2026-03-31", "managerDeadlineAt": "2026-04-15" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/assessments/{id}" payload = { "title": "Q2 Skills Review (final)", "description": "Updated brief.", "allPeople": False, "peopleTypeIds": [""], "employeeDeadlineAt": "2026-03-31", "managerDeadlineAt": "2026-04-15" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ title: 'Q2 Skills Review (final)', description: 'Updated brief.', allPeople: false, peopleTypeIds: [''], employeeDeadlineAt: '2026-03-31', managerDeadlineAt: '2026-04-15' }) }; fetch('https://prod.skillsdbnext.com/api/v1/assessments/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/assessments/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'title' => 'Q2 Skills Review (final)', 'description' => 'Updated brief.', 'allPeople' => false, 'peopleTypeIds' => [ '' ], 'employeeDeadlineAt' => '2026-03-31', 'managerDeadlineAt' => '2026-04-15' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/assessments/{id}" payload := strings.NewReader("{\n \"title\": \"Q2 Skills Review (final)\",\n \"description\": \"Updated brief.\",\n \"allPeople\": false,\n \"peopleTypeIds\": [\n \"\"\n ],\n \"employeeDeadlineAt\": \"2026-03-31\",\n \"managerDeadlineAt\": \"2026-04-15\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/assessments/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"title\": \"Q2 Skills Review (final)\",\n \"description\": \"Updated brief.\",\n \"allPeople\": false,\n \"peopleTypeIds\": [\n \"\"\n ],\n \"employeeDeadlineAt\": \"2026-03-31\",\n \"managerDeadlineAt\": \"2026-04-15\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/assessments/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"title\": \"Q2 Skills Review (final)\",\n \"description\": \"Updated brief.\",\n \"allPeople\": false,\n \"peopleTypeIds\": [\n \"\"\n ],\n \"employeeDeadlineAt\": \"2026-03-31\",\n \"managerDeadlineAt\": \"2026-04-15\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "42" , "title" : "Q2 Skills Review" , "description" : "Annual proficiency check-in." , "status" : "draft" , "tracks" : { "employee" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" }, "manager" : { "status" : "active" , "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : "2026-03-31T00:00:00.000Z" } }, "startedAt" : "2026-03-01T00:00:00.000Z" , "endedAt" : null , "deadlineAt" : null , "managerGradesVisibleAt" : "immediately" , "allPeople" : true , "counts" : { "assigned" : 120 , "completed" : 40 , "employeesAssigned" : 118 , "employeesCompleted" : 60 , "managersAssigned" : 14 , "managersCompleted" : 5 }, "createdAt" : "2026-02-20T09:00:00.000Z" , "updatedAt" : null , "scope" : { "allPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [], "countryIds" : [], "businessRegionIds" : [], "cityIds" : [], "siteIds" : [], "departmentIds" : [ "12" , "15" ], "teamIds" : [], "shiftIds" : [], "peopleTypeIds" : [] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or --- ## Sync a batch of people URL: https://help.skillsdb.com/api-reference/bulk/sync-a-batch-of-people Sync a batch of people cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/bulk/people \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "people": [ { "email": "ada@example.com", "firstName": "Ada", "lastName": "Lovelace", "externalId": "E-10422", "managerEmail": "manager@example.com", "isActive": true, "accessLevel": "basic" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/bulk/people" payload = { "people": [ { "email": "ada@example.com", "firstName": "Ada", "lastName": "Lovelace", "externalId": "E-10422", "managerEmail": "manager@example.com", "isActive": True, "accessLevel": "basic" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ people: [ { email: 'ada@example.com', firstName: 'Ada', lastName: 'Lovelace', externalId: 'E-10422', managerEmail: 'manager@example.com', isActive: true, accessLevel: 'basic' } ] }) }; fetch('https://prod.skillsdbnext.com/api/v1/bulk/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/bulk/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'people' => [ [ 'email' => 'ada@example.com', 'firstName' => 'Ada', 'lastName' => 'Lovelace', 'externalId' => 'E-10422', 'managerEmail' => 'manager@example.com', 'isActive' => true, 'accessLevel' => 'basic' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/bulk/people" payload := strings.NewReader("{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"firstName\": \"Ada\",\n \"lastName\": \"Lovelace\",\n \"externalId\": \"E-10422\",\n \"managerEmail\": \"manager@example.com\",\n \"isActive\": true,\n \"accessLevel\": \"basic\"\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/bulk/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"firstName\": \"Ada\",\n \"lastName\": \"Lovelace\",\n \"externalId\": \"E-10422\",\n \"managerEmail\": \"manager@example.com\",\n \"isActive\": true,\n \"accessLevel\": \"basic\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/bulk/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"firstName\": \"Ada\",\n \"lastName\": \"Lovelace\",\n \"externalId\": \"E-10422\",\n \"managerEmail\": \"manager@example.com\",\n \"isActive\": true,\n \"accessLevel\": \"basic\"\n }\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "results": [ { "index": 0, "email": "ada@example.com", "status": "created", "id": "4821", "error": null } ], "summary": { "total": 100, "created": 12, "updated": 85, "deactivated": 2, "failed": 1 } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "req --- ## Assign people to a career URL: https://help.skillsdb.com/api-reference/career-assignment/assign-people-to-a-career Assign people to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/people \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "people": [ { "email": "ada@example.com", "levelId": "12" } ], "initiationDate": "2026-04-01" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" payload = { "people": [ { "email": "ada@example.com", "levelId": "12" } ], "initiationDate": "2026-04-01" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ people: [{email: 'ada@example.com', levelId: '12'}], initiationDate: '2026-04-01' }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'people' => [ [ 'email' => 'ada@example.com', 'levelId' => '12' ] ], 'initiationDate' => '2026-04-01' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" payload := strings.NewReader("{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"levelId\": \"12\"\n }\n ],\n \"initiationDate\": \"2026-04-01\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"levelId\": \"12\"\n }\n ],\n \"initiationDate\": \"2026-04-01\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"people\": [\n {\n \"email\": \"ada@example.com\",\n \"levelId\": \"12\"\n }\n ],\n \"initiationDate\": \"2026-04-01\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 3 , "message" : "Assigned 3 people" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "emai --- ## Change a person's level URL: https://help.skillsdb.com/api-reference/career-assignment/change-a-persons-level Change a person's level cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "levelId": "13" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}" payload = { "levelId": "13" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({levelId: '13'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'levelId' => '13' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}" payload := strings.NewReader("{\n \"levelId\": \"13\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"levelId\": \"13\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/people/{personId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"levelId\": \"13\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 3 , "message" : "Assigned 3 people" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url" --- ## Get career distribution URL: https://help.skillsdb.com/api-reference/career-assignment/get-career-distribution Get career distribution cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "levels" : [ { "id" : "12" , "label" : "Level 2" , "count" : 17 } ], "flags" : [ { "id" : "12" , "label" : "Level 2" , "count" : 17 } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / distribution Try it Get career distribution cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/distribution", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUST --- ## List a person's careers URL: https://help.skillsdb.com/api-reference/career-assignment/list-a-persons-careers List a person's careers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/careers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "318" , "name" : "Welder" , "careerType" : "Trades" , "isPrevious" : false , "assignedAt" : "2026-03-11T08:22:10.000Z" , "initiationDate" : "2026-04-01T00:00:00.000Z" , "skillsCount" : 24 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / careers Try it List a person's careers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/careers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers", CURLOPT_RETURNTRANSFER => true, --- ## List people assigned to a career URL: https://help.skillsdb.com/api-reference/career-assignment/list-people-assigned-to-a-career List people assigned to a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "4821" , "externalId" : "E-10422" , "firstName" : "Ada" , "lastName" : "Lovelace" , "email" : "ada@example.com" , "level" : { "id" : "12" , "name" : "Level 2" }, "assignedAt" : "2026-03-11T08:22:10.000Z" , "initiationDate" : "2026-04-01T00:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / people Try it List people assigned to a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/people", CURLOPT_RETURNTRANSFER => true, --- ## Unassign a person from every career URL: https://help.skillsdb.com/api-reference/career-assignment/unassign-a-person-from-every-career Unassign a person from every career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/careers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 3 , "message" : "Assigned 3 people" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / careers Try it Unassign a person from every career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/careers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/ --- ## Unassign people from a career URL: https://help.skillsdb.com/api-reference/career-assignment/unassign-people-from-a-career Unassign people from a career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/people \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "emails": [ "ada@example.com", "grace@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" payload = { "emails": ["ada@example.com", "grace@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({emails: ['ada@example.com', 'grace@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'emails' => [ 'ada@example.com', 'grace@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/people" payload := strings.NewReader("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 3 , "message" : "Assigned 3 people" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api --- ## Create a career type URL: https://help.skillsdb.com/api-reference/career-type/create-a-career-type Create a career type cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/career-types \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Job Role", "description": "Line-level roles." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types" payload = { "name": "Job Role", "description": "Line-level roles." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Job Role', description: 'Line-level roles.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/career-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Job Role', 'description' => 'Line-level roles.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/career-types" payload := strings.NewReader("{\n \"name\": \"Job Role\",\n \"description\": \"Line-level roles.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/career-types") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Job Role\",\n \"description\": \"Line-level roles.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/career-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Job Role\",\n \"description\": \"Line-level roles.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Job Role" , "description" : "Line-level roles." , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "det --- ## Delete a career type URL: https://help.skillsdb.com/api-reference/career-type/delete-a-career-type Delete a career type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/career-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/career-types/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/career-types/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/career-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / career-types / {id} Try it Delete a career type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/career-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/career-types/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/career-types/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/career-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "3" , "name" : "Job Role" , "description" : "Line-level roles." , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / career-types / {id} Try it Get a career type cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/career-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $respo --- ## List career types URL: https://help.skillsdb.com/api-reference/career-type/list-career-types List career types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/career-types \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/career-types" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/career-types") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/career-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "3" , "name" : "Job Role" , "description" : "Line-level roles." , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / career-types Try it List career types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/career-types \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/career-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $resp --- ## Update a career type URL: https://help.skillsdb.com/api-reference/career-type/update-a-career-type Update a career type cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/career-types/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Group", "description": "Skill groups." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/career-types/{id}" payload = { "name": "Group", "description": "Skill groups." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Group', description: 'Skill groups.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/career-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/career-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Group', 'description' => 'Skill groups.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/career-types/{id}" payload := strings.NewReader("{\n \"name\": \"Group\",\n \"description\": \"Skill groups.\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/career-types/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Group\",\n \"description\": \"Skill groups.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/career-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Group\",\n \"description\": \"Skill groups.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Job Role" , "description" : "Line-level roles." , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": " --- ## Add a level to a career URL: https://help.skillsdb.com/api-reference/career/add-a-level-to-a-career Add a level to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Senior" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels" payload = { "name": "Senior" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Senior'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Senior' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels" payload := strings.NewReader("{\n \"name\": \"Senior\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Senior\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Senior\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data" : { "id" : "31" , "name" : "Senior" , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skills --- ## Add a section to a career URL: https://help.skillsdb.com/api-reference/career/add-a-section-to-a-career Add a section to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Safety", "description": "Plant safety fundamentals." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections" payload = { "name": "Safety", "description": "Plant safety fundamentals." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Safety', description: 'Plant safety fundamentals.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Safety', 'description' => 'Plant safety fundamentals.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections" payload := strings.NewReader("{\n \"name\": \"Safety\",\n \"description\": \"Plant safety fundamentals.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Safety\",\n \"description\": \"Plant safety fundamentals.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Safety\",\n \"description\": \"Plant safety fundamentals.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data" : { "id" : "77" , "sectionLibraryId" : "12" , "name" : "Safety" , "description" : "Plant safety fundamentals." , "position" : 1 , "minimumRequiredSkills" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { " --- ## Add a skill group to a career URL: https://help.skillsdb.com/api-reference/career/add-a-skill-group-to-a-career Add a skill group to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "name": "Core" }' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups" payload = { "name": "Core" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Core'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Core' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups" payload := strings.NewReader("{\n \"name\": \"Core\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Core\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Core\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data": { "id": "9", "name": "Core", "position": 1 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/se --- ## Add a skill to a career URL: https://help.skillsdb.com/api-reference/career/add-a-skill-to-a-career Add a skill to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillId": "63", "benchmarkId": "7", "sectionId": "77", "requirement": { "isRequired": true, "scope": "going_forward" }, "skillGroupIds": [ "9" ], "trainingRequiresNote": false, "trainingRequiresAttachment": true, "trainingExpiryDays": 0, "trainingExpiryMonths": 6, "trainingExpiryYears": 0 } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills" payload = { "skillId": "63", "benchmarkId": "7", "sectionId": "77", "requirement": { "isRequired": True, "scope": "going_forward" }, "skillGroupIds": ["9"], "trainingRequiresNote": False, "trainingRequiresAttachment": True, "trainingExpiryDays": 0, "trainingExpiryMonths": 6, "trainingExpiryYears": 0 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ skillId: '63', benchmarkId: '7', sectionId: '77', requirement: {isRequired: true, scope: 'going_forward'}, skillGroupIds: ['9'], trainingRequiresNote: false, trainingRequiresAttachment: true, trainingExpiryDays: 0, trainingExpiryMonths: 6, trainingExpiryYears: 0 }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'skillId' => '63', 'benchmarkId' => '7', 'sectionId' => '77', 'requirement' => [ 'isRequired' => true, 'scope' => 'going_forward' ], 'skillGroupIds' => [ '9' ], 'trainingRequiresNote' => false, 'trainingRequiresAttachment' => true, 'trainingExpiryDays' => 0, 'trainingExpiryMonths' => 6, 'trainingExpiryYears' => 0 ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills" payload := strings.NewReader("{\n \"skillId\": \"63\",\n \"benchmarkId\": \"7\",\n \"sectionId\": \"77\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"skillGroupIds\": [\n \"9\"\n ],\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillId\": \"63\",\n \"benchmarkId\": \"7\",\n \"sectionId\": \"77\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"skillGroupIds\": [\n \"9\"\n ],\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillId\": \"63\",\n \"benchmarkId\": \"7\",\n \"sectionId\": \"77\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"skillGroupIds\": [\n \"9\"\n ],\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data" : { "id" : "205" , "skill" : { "id" : "42" , "name" : "Welding" }, "skillDescription" : "MIG and TIG welding." , "sectionId" : "77" , "skillGroupIds" : [ "9" ], "position" : 2 , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" }, "requirement" : { "isRequired" : true , "scope" : "all" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "42" , "name" : "Welding" } }, "trainingEvidence" : { "requiresNote" : false , "requiresAttachment" : true }, "trainingExpiry" : { "days" : 0 , "months" : 6 , "years" : 0 }, "levels" : [ { "levelId" : "31" , "isActive" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" } } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter --- ## Attach an existing section URL: https://help.skillsdb.com/api-reference/career/attach-an-existing-section Attach an existing section cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{sectionLibraryId}/attach") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data" : { "id" : "77" , "sectionLibraryId" : "12" , "name" : "Safety" , "description" : "Plant safety fundamentals." , "position" : 1 , "minimumRequiredSkills" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "ht --- ## Create a career URL: https://help.skillsdb.com/api-reference/career/create-a-career Create a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Maintenance Technician", "description": "Keeps the line running.", "icon": "wrench", "careerTypeId": "3" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers" payload = { "name": "Maintenance Technician", "description": "Keeps the line running.", "icon": "wrench", "careerTypeId": "3" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Maintenance Technician', description: 'Keeps the line running.', icon: 'wrench', careerTypeId: '3' }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Maintenance Technician', 'description' => 'Keeps the line running.', 'icon' => 'wrench', 'careerTypeId' => '3' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers" payload := strings.NewReader("{\n \"name\": \"Maintenance Technician\",\n \"description\": \"Keeps the line running.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Maintenance Technician\",\n \"description\": \"Keeps the line running.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Maintenance Technician\",\n \"description\": \"Keeps the line running.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data": { "id": "18", "name": "Maintenance Technician", "description": "Keeps the line running.", "icon": "wrench", "careerType": { "id": "42", "name": "Welding" }, "levelCount": 3, "isCompleted": false, "isApproved": true, "createdAt": "2026-01-12T08:30:00.000Z", "updatedAt": "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgra --- ## Delete a career URL: https://help.skillsdb.com/api-reference/career/delete-a-career Delete a career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} Try it Delete a career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/a --- ## Delete a level URL: https://help.skillsdb.com/api-reference/career/delete-a-level Delete a level cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 422 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / levels / {levelId} Try it Delete a level cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{l --- ## Delete a skill group URL: https://help.skillsdb.com/api-reference/career/delete-a-skill-group Delete a skill group cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 422 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / skill-groups / {groupId} Try it Delete a skill group cURL curl --request DELETE \ --url --- ## Detach a section URL: https://help.skillsdb.com/api-reference/career/detach-a-section Detach a section cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 422 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / sections / {careerSectionId} Try it Detach a section cURL curl --- ## Get a career URL: https://help.skillsdb.com/api-reference/career/get-a-career Get a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "18" , "name" : "Maintenance Technician" , "description" : "Keeps the line running." , "icon" : "wrench" , "careerType" : { "id" : "42" , "name" : "Welding" }, "levelCount" : 3 , "isCompleted" : false , "isApproved" : true , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} Try it Get a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUST --- ## Get a career's full definition URL: https://help.skillsdb.com/api-reference/career/get-a-careers-full-definition Get a career's full definition cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/definition \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/definition" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/definition', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/definition", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/definition" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/definition") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/definition") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "18" , "name" : "Maintenance Technician" , "description" : "Keeps the line running." , "icon" : "wrench" , "careerType" : { "id" : "42" , "name" : "Welding" }, "levelCount" : 3 , "isCompleted" : false , "isApproved" : true , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "settings" : { "proficiencyGrading" : { "isEnabled" : true }, "trainingDates" : { "isEnabled" : false , "timeline" : { "days" : 0 , "months" : 6 , "years" : 0 } }, "hideNonRequiredSkills" : { "isEnabled" : false }, "assessments" : { "isEnabled" : true }, "dashboard" : { "isEnabled" : false , "showCareerDescription" : true , "showTrainingDatesSummary" : true , "showProficiencySummary" : true , "showPinnedPages" : true } }, "gradingScale" : [ { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true } ], "levels" : [ { "id" : "31" , "name" : "Senior" , "position" : 2 } ], "sections" : [ { "id" : "77" , "sectionLibraryId" : "12" , "name" : "Safety" , "description" : "Plant safety fundamentals." , "position" : 1 , "minimumRequiredSkills" : 3 } ], "skillGroups" : [ { "id" : "9" , "name" : "Core" , "position" : 1 } ], "skills" : [ { "id" : "205" , "skill" : { "id" : "42" , "name" : "Welding" }, "skillDescription" : "MIG and TIG welding." , "sectionId" : "77" , "skillGroupIds" : [ "9" ], "position" : 2 , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" }, "requirement" : { "isRequired" : true , "scope" : "all" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "42" , "name" : "Welding" } }, "trainingEvidence" : { "requiresNote" : false , "requiresAttachment" : true }, "trainingExpiry" : { "days" : 0 , "months" : 6 , "years" : 0 }, "levels" : [ { "levelId" : "31" , "isActive" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" } } ] } ], "learnings" : [ { "id" : "301" , "learning" : { "id" : "42" , "name" : "Welding" }, "sectionId" : "77" , "position" : 1 , "isRequired" : true , "requiredAtLevelIds" : [ "31" ] } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "htt --- ## Get a career's settings URL: https://help.skillsdb.com/api-reference/career/get-a-careers-settings Get a career's settings cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/settings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/settings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/settings") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/settings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "proficiencyGrading" : { "isEnabled" : true }, "trainingDates" : { "isEnabled" : false , "timeline" : { "days" : 0 , "months" : 6 , "years" : 0 } }, "hideNonRequiredSkills" : { "isEnabled" : false }, "assessments" : { "isEnabled" : true }, "dashboard" : { "isEnabled" : false , "showCareerDescription" : true , "showTrainingDatesSummary" : true , "showProficiencySummary" : true , "showPinnedPages" : true } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / settings Try it Get a career's settings cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/settings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/settings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/activity", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/activity" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/activity") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/activity") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "event" : "career_updated" , "description" : "Career renamed" , "performedById" : "88" , "performedAt" : "2026-03-02T14:00:00.000Z" , "emailSent" : false , "relatedPersonId" : "91" , "relatedSkillId" : "63" , "relatedSectionId" : "77" , "relatedLevelId" : "31" , "bulkGroupId" : "b7f3…" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / activity Try it List a career's activity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/activity \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/ --- ## List a career's learnings URL: https://help.skillsdb.com/api-reference/career/list-a-careers-learnings List a career's learnings cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "301" , "learning" : { "id" : "42" , "name" : "Welding" }, "sectionId" : "77" , "position" : 1 , "isRequired" : true , "requiredAtLevelIds" : [ "31" ] } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / learnings Try it List a career's learnings cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/learnings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => --- ## List a career's levels URL: https://help.skillsdb.com/api-reference/career/list-a-careers-levels List a career's levels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "31" , "name" : "Senior" , "position" : 2 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / levels Try it List a career's levels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $resp --- ## List a career's sections URL: https://help.skillsdb.com/api-reference/career/list-a-careers-sections List a career's sections cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "77" , "sectionLibraryId" : "12" , "name" : "Safety" , "description" : "Plant safety fundamentals." , "position" : 1 , "minimumRequiredSkills" : 3 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / sections Try it List a career's sections cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_V --- ## List a career's skill groups URL: https://help.skillsdb.com/api-reference/career/list-a-careers-skill-groups List a career's skill groups cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "9" , "name" : "Core" , "position" : 1 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / skill-groups Try it List a career's skill groups cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUE --- ## List a career's skills URL: https://help.skillsdb.com/api-reference/career/list-a-careers-skills List a career's skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "205" , "skill" : { "id" : "42" , "name" : "Welding" }, "skillDescription" : "MIG and TIG welding." , "sectionId" : "77" , "skillGroupIds" : [ "9" ], "position" : 2 , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" }, "requirement" : { "isRequired" : true , "scope" : "all" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "42" , "name" : "Welding" } }, "trainingEvidence" : { "requiresNote" : false , "requiresAttachment" : true }, "trainingExpiry" : { "days" : 0 , "months" : 6 , "years" : 0 }, "levels" : [ { "levelId" : "31" , "isActive" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" } } ] } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / skills Try it List a career's skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET& --- ## List all careers URL: https://help.skillsdb.com/api-reference/career/list-all-careers List all careers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "18", "name": "Maintenance Technician", "description": "Keeps the line running.", "icon": "wrench", "careerType": { "id": "42", "name": "Welding" }, "levelCount": 3, "isCompleted": false, "isApproved": true, "createdAt": "2026-01-12T08:30:00.000Z", "updatedAt": "2026-03-02T14:00:00.000Z" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers Try it List all careers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST --- ## Remove a skill from a career URL: https://help.skillsdb.com/api-reference/career/remove-a-skill-from-a-career Remove a skill from a career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 422 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / skills / {careerSkillId} Try it Remove a skill from a career cURL curl --reques --- ## Rename a level URL: https://help.skillsdb.com/api-reference/career/rename-a-level Rename a level cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "name": "Lead" }' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}" payload = { "name": "Lead" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Lead'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Lead' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}" payload := strings.NewReader("{\n \"name\": \"Lead\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Lead\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/{levelId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Lead\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : { "id" : "31" , "name" : "Senior" , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.co --- ## Rename a skill group URL: https://help.skillsdb.com/api-reference/career/rename-a-skill-group Rename a skill group cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Operations" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}" payload = { "name": "Operations" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Operations'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Operations' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}" payload := strings.NewReader("{\n \"name\": \"Operations\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Operations\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/{groupId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Operations\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : { "id" : "9" , "name" : "Core" , "position" : 1 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal --- ## Reorder levels URL: https://help.skillsdb.com/api-reference/career/reorder-levels Reorder levels cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "31", "29", "34" ], "levelIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder" payload = { "ids": ["31", "29", "34"], "levelIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['31', '29', '34'], levelIds: ['']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '31', '29', '34' ], 'levelIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"31\",\n \"29\",\n \"34\"\n ],\n \"levelIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"31\",\n \"29\",\n \"34\"\n ],\n \"levelIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/levels/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"31\",\n \"29\",\n \"34\"\n ],\n \"levelIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : [ { "id" : "31" , "name" : "Senior" , "position" : 2 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skil --- ## Reorder sections URL: https://help.skillsdb.com/api-reference/career/reorder-sections Reorder sections cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "77", "78" ], "sectionIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder" payload = { "ids": ["77", "78"], "sectionIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['77', '78'], sectionIds: ['']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '77', '78' ], 'sectionIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"77\",\n \"78\"\n ],\n \"sectionIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"77\",\n \"78\"\n ],\n \"sectionIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"77\",\n \"78\"\n ],\n \"sectionIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : [ { "id" : "77" , "sectionLibraryId" : "12" , "name" : "Safety" , "description" : "Plant safety fundamentals." , "position" : 1 , "minimumRequiredSkills" : 3 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } --- ## Reorder skill groups URL: https://help.skillsdb.com/api-reference/career/reorder-skill-groups Reorder skill groups cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "9", "11" ], "skillGroupIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder" payload = { "ids": ["9", "11"], "skillGroupIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['9', '11'], skillGroupIds: ['']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '9', '11' ], 'skillGroupIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"9\",\n \"11\"\n ],\n \"skillGroupIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"9\",\n \"11\"\n ],\n \"skillGroupIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skill-groups/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"9\",\n \"11\"\n ],\n \"skillGroupIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : [ { "id" : "9" , "name" : "Core" , "position" : 1 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skill --- ## Set a skill's groups URL: https://help.skillsdb.com/api-reference/career/set-a-skills-groups Set a skill's groups cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "skillGroupIds": [ "9" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups" payload = { "skillGroupIds": ["9"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillGroupIds: ['9']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'skillGroupIds' => [ '9' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups" payload := strings.NewReader("{\n \"skillGroupIds\": [\n \"9\"\n ]\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillGroupIds\": [\n \"9\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/groups") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillGroupIds\": [\n \"9\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data": { "id": "205", "skill": { "id": "42", "name": "Welding" }, "skillDescription": "MIG and TIG welding.", "sectionId": "77", "skillGroupIds": [ "9" ], "position": 2, "benchmark": { "id": "7", "grade": 3, "label": "Proficient" }, "requirement": { "isRequired": true, "scope": "all", "effectiveFrom": "2026-03-01T00:00:00.000Z", "setBy": { "id": "42", "name": "Welding" } }, "trainingEvidence": { "requiresNote": false, "requiresAttachment": true }, "trainingExpiry": { "days": 0, "months": 6, "years": 0 }, "levels": [ { "levelId": "31", "isActive": true, "benchmark": { "id": "7", "grade": 3, "label": "Proficient" } } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "d --- ## Set a skill's per-level activation URL: https://help.skillsdb.com/api-reference/career/set-a-skills-per-level-activation Set a skill's per-level activation cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "isActive": true, "benchmarkId": "7" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}" payload = { "isActive": True, "benchmarkId": "7" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({isActive: true, benchmarkId: '7'}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'isActive' => true, 'benchmarkId' => '7' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}" payload := strings.NewReader("{\n \"isActive\": true,\n \"benchmarkId\": \"7\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"isActive\": true,\n \"benchmarkId\": \"7\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}/levels/{levelId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"isActive\": true,\n \"benchmarkId\": \"7\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : { "id" : "205" , "skill" : { "id" : "42" , "name" : "Welding" }, "skillDescription" : "MIG and TIG welding." , "sectionId" : "77" , "skillGroupIds" : [ "9" ], "position" : 2 , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" }, "requirement" : { "isRequired" : true , "scope" : "all" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "42" , "name" : "Welding" } }, "trainingEvidence" : { "requiresNote" : false , "requiresAttachment" : true }, "trainingExpiry" : { "days" : 0 , "months" : 6 , "years" : 0 }, "levels" : [ { "levelId" : "31" , "isActive" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" } } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } --- ## Update a career URL: https://help.skillsdb.com/api-reference/career/update-a-career Update a career cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Maintenance Technician II", "description": "Updated description.", "icon": "wrench", "careerTypeId": "3" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}" payload = { "name": "Maintenance Technician II", "description": "Updated description.", "icon": "wrench", "careerTypeId": "3" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Maintenance Technician II', description: 'Updated description.', icon: 'wrench', careerTypeId: '3' }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Maintenance Technician II', 'description' => 'Updated description.', 'icon' => 'wrench', 'careerTypeId' => '3' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}" payload := strings.NewReader("{\n \"name\": \"Maintenance Technician II\",\n \"description\": \"Updated description.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Maintenance Technician II\",\n \"description\": \"Updated description.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Maintenance Technician II\",\n \"description\": \"Updated description.\",\n \"icon\": \"wrench\",\n \"careerTypeId\": \"3\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "18" , "name" : "Maintenance Technician" , "description" : "Keeps the line running." , "icon" : "wrench" , "careerType" : { "id" : "42" , "name" : "Welding" }, "levelCount" : 3 , "isCompleted" : false , "isApproved" : true , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters --- ## Update a career section URL: https://help.skillsdb.com/api-reference/career/update-a-career-section Update a career section cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId} \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Safety fundamentals", "description": "Site safety, PPE and permits.", "minimumRequiredSkills": 3 } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}" payload = { "name": "Safety fundamentals", "description": "Site safety, PPE and permits.", "minimumRequiredSkills": 3 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Safety fundamentals', description: 'Site safety, PPE and permits.', minimumRequiredSkills: 3 }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Safety fundamentals', 'description' => 'Site safety, PPE and permits.', 'minimumRequiredSkills' => 3 ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}" payload := strings.NewReader("{\n \"name\": \"Safety fundamentals\",\n \"description\": \"Site safety, PPE and permits.\",\n \"minimumRequiredSkills\": 3\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Safety fundamentals\",\n \"description\": \"Site safety, PPE and permits.\",\n \"minimumRequiredSkills\": 3\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/sections/{careerSectionId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Safety fundamentals\",\n \"description\": \"Site safety, PPE and permits.\",\n \"minimumRequiredSkills\": 3\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data": { "id": "77", "sectionLibraryId": "12", "name": "Safety", "description": "Plant safety fundamentals.", "position": 1, "minimumRequiredSkills": 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/sett --- ## Update a career's settings URL: https://help.skillsdb.com/api-reference/career/update-a-careers-settings Update a career's settings cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/settings \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "proficiencyGrading": { "isEnabled": true }, "trainingDates": { "isEnabled": true, "timeline": { "days": 0, "months": 6, "years": 0 } }, "hideNonRequiredSkills": { "isEnabled": true }, "assessments": { "isEnabled": true }, "dashboard": { "isEnabled": true, "showCareerDescription": true, "showTrainingDatesSummary": true, "showProficiencySummary": true, "showPinnedPages": true } } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings" payload = { "proficiencyGrading": { "isEnabled": True }, "trainingDates": { "isEnabled": True, "timeline": { "days": 0, "months": 6, "years": 0 } }, "hideNonRequiredSkills": { "isEnabled": True }, "assessments": { "isEnabled": True }, "dashboard": { "isEnabled": True, "showCareerDescription": True, "showTrainingDatesSummary": True, "showProficiencySummary": True, "showPinnedPages": True } } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ proficiencyGrading: {isEnabled: true}, trainingDates: {isEnabled: true, timeline: {days: 0, months: 6, years: 0}}, hideNonRequiredSkills: {isEnabled: true}, assessments: {isEnabled: true}, dashboard: { isEnabled: true, showCareerDescription: true, showTrainingDatesSummary: true, showProficiencySummary: true, showPinnedPages: true } }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/settings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'proficiencyGrading' => [ 'isEnabled' => true ], 'trainingDates' => [ 'isEnabled' => true, 'timeline' => [ 'days' => 0, 'months' => 6, 'years' => 0 ] ], 'hideNonRequiredSkills' => [ 'isEnabled' => true ], 'assessments' => [ 'isEnabled' => true ], 'dashboard' => [ 'isEnabled' => true, 'showCareerDescription' => true, 'showTrainingDatesSummary' => true, 'showProficiencySummary' => true, 'showPinnedPages' => true ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/settings" payload := strings.NewReader("{\n \"proficiencyGrading\": {\n \"isEnabled\": true\n },\n \"trainingDates\": {\n \"isEnabled\": true,\n \"timeline\": {\n \"days\": 0,\n \"months\": 6,\n \"years\": 0\n }\n },\n \"hideNonRequiredSkills\": {\n \"isEnabled\": true\n },\n \"assessments\": {\n \"isEnabled\": true\n },\n \"dashboard\": {\n \"isEnabled\": true,\n \"showCareerDescription\": true,\n \"showTrainingDatesSummary\": true,\n \"showProficiencySummary\": true,\n \"showPinnedPages\": true\n }\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/settings") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"proficiencyGrading\": {\n \"isEnabled\": true\n },\n \"trainingDates\": {\n \"isEnabled\": true,\n \"timeline\": {\n \"days\": 0,\n \"months\": 6,\n \"years\": 0\n }\n },\n \"hideNonRequiredSkills\": {\n \"isEnabled\": true\n },\n \"assessments\": {\n \"isEnabled\": true\n },\n \"dashboard\": {\n \"isEnabled\": true,\n \"showCareerDescription\": true,\n \"showTrainingDatesSummary\": true,\n \"showProficiencySummary\": true,\n \"showPinnedPages\": true\n }\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/settings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"proficiencyGrading\": {\n \"isEnabled\": true\n },\n \"trainingDates\": {\n \"isEnabled\": true,\n \"timeline\": {\n \"days\": 0,\n \"months\": 6,\n \"years\": 0\n }\n },\n \"hideNonRequiredSkills\": {\n \"isEnabled\": true\n },\n \"assessments\": {\n \"isEnabled\": true\n },\n \"dashboard\": {\n \"isEnabled\": true,\n \"showCareerDescription\": true,\n \"showTrainingDatesSummary\": true,\n \"showProficiencySummary\": true,\n \"showPinnedPages\": true\n }\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : { "proficiencyGrading" : { "isEnabled" : true }, "trainingDates" : { "isEnabled" : false , "timeline" : { "days" : 0 , "months" : 6 , "years" : 0 } }, "hideNonRequiredSkills" : { "isEnabled" : false }, "assessments" : { "isEnabled" : true }, "dashboard" : { "isEnabled" : false , "showCareerDescription" : true , "showTrainingDatesSummary --- ## Update a skill on a career URL: https://help.skillsdb.com/api-reference/career/update-a-skill-on-a-career Update a skill on a career cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "benchmarkId": "7", "requirement": { "isRequired": true, "scope": "going_forward" }, "trainingRequiresNote": false, "trainingRequiresAttachment": true, "trainingExpiryDays": 0, "trainingExpiryMonths": 6, "trainingExpiryYears": 0 } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}" payload = { "benchmarkId": "7", "requirement": { "isRequired": True, "scope": "going_forward" }, "trainingRequiresNote": False, "trainingRequiresAttachment": True, "trainingExpiryDays": 0, "trainingExpiryMonths": 6, "trainingExpiryYears": 0 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ benchmarkId: '7', requirement: {isRequired: true, scope: 'going_forward'}, trainingRequiresNote: false, trainingRequiresAttachment: true, trainingExpiryDays: 0, trainingExpiryMonths: 6, trainingExpiryYears: 0 }) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'benchmarkId' => '7', 'requirement' => [ 'isRequired' => true, 'scope' => 'going_forward' ], 'trainingRequiresNote' => false, 'trainingRequiresAttachment' => true, 'trainingExpiryDays' => 0, 'trainingExpiryMonths' => 6, 'trainingExpiryYears' => 0 ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}" payload := strings.NewReader("{\n \"benchmarkId\": \"7\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"benchmarkId\": \"7\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/skills/{careerSkillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"benchmarkId\": \"7\",\n \"requirement\": {\n \"isRequired\": true,\n \"scope\": \"going_forward\"\n },\n \"trainingRequiresNote\": false,\n \"trainingRequiresAttachment\": true,\n \"trainingExpiryDays\": 0,\n \"trainingExpiryMonths\": 6,\n \"trainingExpiryYears\": 0\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : { "id" : "205" , "skill" : { "id" : "42" , "name" : "Welding" }, "skillDescription" : "MIG and TIG welding." , "sectionId" : "77" , "skillGroupIds" : [ "9" ], "position" : 2 , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" }, "requirement" : { "isRequired" : true , "scope" : "all" , "effectiveFrom" : "2026-03-01T00:00:00.000Z" , "setBy" : { "id" : "42" , "name" : "Welding" } }, "trainingEvidence" : { "requiresNote" : false , "requiresAttachment" : true }, "trainingExpiry" : { "days" : 0 , "months" : 6 , "years" : 0 }, "levels" : [ { "levelId" : "31" , "isActive" : true , "benchmark" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" } } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or --- ## Create a certification type URL: https://help.skillsdb.com/api-reference/certification-type/create-a-certification-type Create a certification type cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/certification-types \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Regulatory", "description": "Mandated by law or regulator." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types" payload = { "name": "Regulatory", "description": "Mandated by law or regulator." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Regulatory', description: 'Mandated by law or regulator.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/certification-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Regulatory', 'description' => 'Mandated by law or regulator.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types" payload := strings.NewReader("{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/certification-types") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } --- ## Delete a certification type URL: https://help.skillsdb.com/api-reference/certification-type/delete-a-certification-type Delete a certification type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/certification-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certification-types / {id} Try it Delete a certification type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/certification-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/{id}', options) .then(res => res.json()) .then(res = --- ## Get a certification type URL: https://help.skillsdb.com/api-reference/certification-type/get-a-certification-type Get a certification type cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certification-types / {id} Try it Get a certification type cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT --- ## List certification types URL: https://help.skillsdb.com/api-reference/certification-type/list-certification-types List certification types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-types \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certification-types") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certification-types Try it List certification types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-types \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOU --- ## Reorder certification types URL: https://help.skillsdb.com/api-reference/certification-type/reorder-certification-types Reorder certification types cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/certification-types/reorder \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "4", "2", "7" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/reorder" payload = { "ids": ["4", "2", "7"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['4', '2', '7']}) }; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '4', '2', '7' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"4\",\n \"2\",\n \"7\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/certification-types/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"4\",\n \"2\",\n \"7\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"4\",\n \"2\",\n \"7\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : [ { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error" --- ## Update a certification type URL: https://help.skillsdb.com/api-reference/certification-type/update-a-certification-type Update a certification type cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/certification-types/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Regulatory", "description": "Mandated by law or regulator." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" payload = { "name": "Regulatory", "description": "Mandated by law or regulator." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Regulatory', description: 'Mandated by law or regulator.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/certification-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Regulatory', 'description' => 'Mandated by law or regulator.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-types/{id}" payload := strings.NewReader("{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Regulatory\",\n \"description\": \"Mandated by law or regulator.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "4" , "name" : "Regulatory" , "description" : "Mandated by law or regulator." , "position" : 1 , "certificationCount" : 6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be --- ## Create a certification URL: https://help.skillsdb.com/api-reference/certification/create-a-certification Create a certification cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/certifications \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Forklift Operator Licence", "description": "Required for warehouse floor access.", "certificationTypeId": "4", "issuingAuthorityName": "National Safety Council", "issuingAuthorityUrl": "https://www.nsc.org" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications" payload = { "name": "Forklift Operator Licence", "description": "Required for warehouse floor access.", "certificationTypeId": "4", "issuingAuthorityName": "National Safety Council", "issuingAuthorityUrl": "https://www.nsc.org" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Forklift Operator Licence', description: 'Required for warehouse floor access.', certificationTypeId: '4', issuingAuthorityName: 'National Safety Council', issuingAuthorityUrl: 'https://www.nsc.org' }) }; fetch('https://prod.skillsdbnext.com/api/v1/certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Forklift Operator Licence', 'description' => 'Required for warehouse floor access.', 'certificationTypeId' => '4', 'issuingAuthorityName' => 'National Safety Council', 'issuingAuthorityUrl' => 'https://www.nsc.org' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications" payload := strings.NewReader("{\n \"name\": \"Forklift Operator Licence\",\n \"description\": \"Required for warehouse floor access.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/certifications") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Forklift Operator Licence\",\n \"description\": \"Required for warehouse floor access.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Forklift Operator Licence\",\n \"description\": \"Required for warehouse floor access.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "87" , "name" : "Forklift Operator Licence" , "description" : "Required for warehouse floor access." , "type" : { "id" : "4" , "name" : "Regulatory" }, "issuingAuthorityName" : "National Safety Council" , "issuingAuthorityUrl" : "https://www.nsc.org" , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "holderCount" : 14 , "holdersWithFileCount" : 9 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], " --- ## Delete a certification URL: https://help.skillsdb.com/api-reference/certification/delete-a-certification Delete a certification cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/certifications/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications / {id} Try it Delete a certification cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certifications/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "87" , "name" : "Forklift Operator Licence" , "description" : "Required for warehouse floor access." , "type" : { "id" : "4" , "name" : "Regulatory" }, "issuingAuthorityName" : "National Safety Council" , "issuingAuthorityUrl" : "https://www.nsc.org" , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "holderCount" : 14 , "holdersWithFileCount" : 9 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications / {id} Try it Get a certification cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certifications") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "87" , "name" : "Forklift Operator Licence" , "description" : "Required for warehouse floor access." , "type" : { "id" : "4" , "name" : "Regulatory" }, "issuingAuthorityName" : "National Safety Council" , "issuingAuthorityUrl" : "https://www.nsc.org" , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "holderCount" : 14 , "holdersWithFileCount" : 9 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications Try it List certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Forklift Operator Licence (Class 2)", "description": "Renewed every three years.", "certificationTypeId": "4", "issuingAuthorityName": "National Safety Council", "issuingAuthorityUrl": "https://www.nsc.org" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}" payload = { "name": "Forklift Operator Licence (Class 2)", "description": "Renewed every three years.", "certificationTypeId": "4", "issuingAuthorityName": "National Safety Council", "issuingAuthorityUrl": "https://www.nsc.org" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Forklift Operator Licence (Class 2)', description: 'Renewed every three years.', certificationTypeId: '4', issuingAuthorityName: 'National Safety Council', issuingAuthorityUrl: 'https://www.nsc.org' }) }; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Forklift Operator Licence (Class 2)', 'description' => 'Renewed every three years.', 'certificationTypeId' => '4', 'issuingAuthorityName' => 'National Safety Council', 'issuingAuthorityUrl' => 'https://www.nsc.org' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}" payload := strings.NewReader("{\n \"name\": \"Forklift Operator Licence (Class 2)\",\n \"description\": \"Renewed every three years.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/certifications/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Forklift Operator Licence (Class 2)\",\n \"description\": \"Renewed every three years.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Forklift Operator Licence (Class 2)\",\n \"description\": \"Renewed every three years.\",\n \"certificationTypeId\": \"4\",\n \"issuingAuthorityName\": \"National Safety Council\",\n \"issuingAuthorityUrl\": \"https://www.nsc.org\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "87" , "name" : "Forklift Operator Licence" , "description" : "Required for warehouse floor access." , "type" : { "id" : "4" , "name" : "Regulatory" }, "issuingAuthorityName" : "National Safety Council" , "issuingAuthorityUrl" : "https://www.nsc.org" , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "holderCount" : 14 , "holdersWithFileCount" : 9 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : "2026-03-02T14:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shor --- ## Apply flags at the career scope URL: https://help.skillsdb.com/api-reference/flags/apply-flags-at-the-career-scope Apply flags at the career scope cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "applied" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "c --- ## Apply flags at the section scope URL: https://help.skillsdb.com/api-reference/flags/apply-flags-at-the-section-scope Apply flags at the section scope cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ], "sectionId": "77" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"], "sectionId": "77" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com'], sectionId: '77' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ], 'sectionId' => '77' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "applied" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Valida --- ## Apply flags at the skill-group scope URL: https://help.skillsdb.com/api-reference/flags/apply-flags-at-the-skill-group-scope Apply flags at the skill-group scope cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ], "skillGroupId": "9" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"], "skillGroupId": "9" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com'], skillGroupId: '9' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ], 'skillGroupId' => '9' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "applied" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-d --- ## Apply flags at the skill scope URL: https://help.skillsdb.com/api-reference/flags/apply-flags-at-the-skill-scope Apply flags at the skill scope cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillId": "63", "flagId": "7", "emails": [ "ada@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills" payload = { "skillId": "63", "flagId": "7", "emails": ["ada@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillId: '63', flagId: '7', emails: ['ada@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'skillId' => '63', 'flagId' => '7', 'emails' => [ 'ada@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills" payload := strings.NewReader("{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "applied" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https --- ## Assign people flags to a person URL: https://help.skillsdb.com/api-reference/flags/assign-people-flags-to-a-person Assign people flags to a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "flagIds": [ "7", "3" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" payload = { "flagIds": ["7", "3"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({flagIds: ['7', '3']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'flagIds' => [ '7', '3' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" payload := strings.NewReader("{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "flag" : { "id" : "42" , "name" : "Welding" }, "person" : { "id" : "42" , "name" : "Welding" }, "assignedById" : "88" , "assignedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be --- ## Check whether the acting identity can see people flags URL: https://help.skillsdb.com/api-reference/flags/check-whether-the-acting-identity-can-see-people-flags Check whether the acting identity can see people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "canSeePeopleFlags" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / visibility / me Try it Check whether the acting identity can see people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/visibility/me", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEA --- ## Count trainers for a skill group URL: https://help.skillsdb.com/api-reference/flags/count-trainers-for-a-skill-group Count trainers for a skill group cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "trainerCount" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-groups / {id} / trainer-count Try it Count trainers for a skill group cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-groups/{id}/trainer-count", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT --- ## Count what depends on a people flag URL: https://help.skillsdb.com/api-reference/flags/count-what-depends-on-a-people-flag Count what depends on a people flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "peopleCount" : 12 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / {id} / dependencies Try it Count what depends on a people flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/dependencies", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPH --- ## Count what depends on a skill flag URL: https://help.skillsdb.com/api-reference/flags/count-what-depends-on-a-skill-flag Count what depends on a skill flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "skillAssignments" : 4 , "sectionAssignments" : 2 , "careerAssignments" : 1 , "skillGroupAssignments" : 0 , "total" : 7 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags / {id} / dependencies Try it Count what depends on a skill flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/dependencies", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLO --- ## Create a people flag URL: https://help.skillsdb.com/api-reference/flags/create-a-people-flag Create a people flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-flags \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags" payload = { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'High potential', description: 'Succession candidates.', color: '#F59E0B' }) }; fetch('https://prod.skillsdbnext.com/api/v1/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'High potential', 'description' => 'Succession candidates.', 'color' => '#F59E0B' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags" payload := strings.NewReader("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-flags") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", --- ## Create a skill flag URL: https://help.skillsdb.com/api-reference/flags/create-a-skill-flag Create a skill flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "designatesTrainer": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags" payload = { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "designatesTrainer": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'High potential', description: 'Succession candidates.', color: '#F59E0B', designatesTrainer: false }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'High potential', 'description' => 'Succession candidates.', 'color' => '#F59E0B', 'designatesTrainer' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags" payload := strings.NewReader("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flags") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/valida --- ## Delete a people flag URL: https://help.skillsdb.com/api-reference/flags/delete-a-people-flag Delete a people flag cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people-flags/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / {id} Try it Delete a people flag cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags / {id} Try it Delete a skill flag cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / {id} / disable Try it Disable a people flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/disable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Be --- ## Disable a skill flag URL: https://help.skillsdb.com/api-reference/flags/disable-a-skill-flag Disable a skill flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags / {id} / disable Try it Disable a skill flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/disable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Author --- ## Enable a people flag URL: https://help.skillsdb.com/api-reference/flags/enable-a-people-flag Enable a people flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / {id} / enable Try it Enable a people flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/enable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer --- ## Enable a skill flag URL: https://help.skillsdb.com/api-reference/flags/enable-a-skill-flag Enable a skill flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags / {id} / enable Try it Enable a skill flag cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/enable" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: &#x --- ## Get a skill flag URL: https://help.skillsdb.com/api-reference/flags/get-a-skill-flag Get a skill flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags / {id} Try it Get a skill flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: B --- ## Get the people-flag visibility setting URL: https://help.skillsdb.com/api-reference/flags/get-the-people-flag-visibility-setting Get the people-flag visibility setting cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/visibility \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/visibility" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/visibility', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/visibility", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/visibility" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-flags/visibility") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/visibility") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "visibleToAdmins" : true , "visibleToFullAccess" : true , "visibleToManagers" : true , "visibleToEmployees" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / visibility Try it Get the people-flag visibility setting cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/visibility \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/visibility" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/visibility', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/visibility", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GE --- ## List a person's people flags URL: https://help.skillsdb.com/api-reference/flags/list-a-persons-people-flags List a person's people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "flag" : { "id" : "42" , "name" : "Welding" }, "person" : { "id" : "42" , "name" : "Welding" }, "assignedById" : "88" , "assignedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / people-flags Try it List a person's people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-fl --- ## List people carrying a flag URL: https://help.skillsdb.com/api-reference/flags/list-people-carrying-a-flag List people carrying a flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "flag" : { "id" : "42" , "name" : "Welding" }, "person" : { "id" : "42" , "name" : "Welding" }, "assignedById" : "88" , "assignedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags / {id} / people Try it List people carrying a flag cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 1 --- ## List people flags URL: https://help.skillsdb.com/api-reference/flags/list-people-flags List people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-flags") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-flags Try it List people flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-flags \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " --- ## List skill flags URL: https://help.skillsdb.com/api-reference/flags/list-skill-flags List skill flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-flags") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "7", "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "isEnabled": true, "isSystemDefault": false, "position": 2, "designatesTrainer": true } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flags Try it List skill flags cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flags \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "flag" : { "id" : "42" , "name" : "Welding" }, "personId" : "91" , "careerId" : "18" , "scopeId" : "77" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-flag-assignments / {scope} Try it Query skill-flag assignments at a scope cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/{scope}", CURLOPT_RETURNTRANSFER => true, CURLOPT_EN --- ## Remove flags at the career scope URL: https://help.skillsdb.com/api-reference/flags/remove-flags-at-the-career-scope Remove flags at the career scope cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "removed" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "fiel --- ## Remove flags at the section scope URL: https://help.skillsdb.com/api-reference/flags/remove-flags-at-the-section-scope Remove flags at the section scope cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ], "sectionId": "77" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"], "sectionId": "77" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com'], sectionId: '77' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ], 'sectionId' => '77' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/sections") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"sectionId\": \"77\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "removed" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", " --- ## Remove flags at the skill-group scope URL: https://help.skillsdb.com/api-reference/flags/remove-flags-at-the-skill-group-scope Remove flags at the skill-group scope cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "careerId": "18", "flagId": "7", "emails": [ "ada@example.com", "grace@example.com" ], "skillGroupId": "9" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups" payload = { "careerId": "18", "flagId": "7", "emails": ["ada@example.com", "grace@example.com"], "skillGroupId": "9" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ careerId: '18', flagId: '7', emails: ['ada@example.com', 'grace@example.com'], skillGroupId: '9' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'careerId' => '18', 'flagId' => '7', 'emails' => [ 'ada@example.com', 'grace@example.com' ], 'skillGroupId' => '9' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups" payload := strings.NewReader("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skill-groups") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"careerId\": \"18\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ],\n \"skillGroupId\": \"9\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "removed" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.ski --- ## Remove flags at the skill scope URL: https://help.skillsdb.com/api-reference/flags/remove-flags-at-the-skill-scope Remove flags at the skill scope cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillId": "63", "flagId": "7", "emails": [ "ada@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills" payload = { "skillId": "63", "flagId": "7", "emails": ["ada@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillId: '63', flagId: '7', emails: ['ada@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'skillId' => '63', 'flagId' => '7', 'emails' => [ 'ada@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills" payload := strings.NewReader("{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flag-assignments/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillId\": \"63\",\n \"flagId\": \"7\",\n \"emails\": [\n \"ada@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "removed" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { --- ## Remove people flags from a person URL: https://help.skillsdb.com/api-reference/flags/remove-people-flags-from-a-person Remove people flags from a person cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "flagIds": [ "7", "3" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" payload = { "flagIds": ["7", "3"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({flagIds: ['7', '3']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'flagIds' => [ '7', '3' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags" payload := strings.NewReader("{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/people-flags") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"flagIds\": [\n \"7\",\n \"3\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "flag" : { "id" : "42" , "name" : "Welding" }, "person" : { "id" : "42" , "name" : "Welding" }, "assignedById" : "88" , "assignedAt" : "2026-03-02T14:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail" --- ## Reorder people flags URL: https://help.skillsdb.com/api-reference/flags/reorder-people-flags Reorder people flags cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-flags/reorder \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "7", "3", "9" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/reorder" payload = { "ids": ["7", "3", "9"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['7', '3', '9']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '7', '3', '9' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-flags/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": " --- ## Reorder skill flags URL: https://help.skillsdb.com/api-reference/flags/reorder-skill-flags Reorder skill flags cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/reorder \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "7", "3", "9" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/reorder" payload = { "ids": ["7", "3", "9"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['7', '3', '9']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '7', '3', '9' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-flags/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"7\",\n \"3\",\n \"9\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": [ { "id": "7", "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "isEnabled": true, "isSystemDefault": false, "position": 2, "designatesTrainer": true } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 --- ## Set whether a skill flag designates a trainer URL: https://help.skillsdb.com/api-reference/flags/set-whether-a-skill-flag-designates-a-trainer Set whether a skill flag designates a trainer cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "designatesTrainer": true } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation" payload = { "designatesTrainer": True } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({designatesTrainer: true}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'designatesTrainer' => true ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation" payload := strings.NewReader("{\n \"designatesTrainer\": true\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"designatesTrainer\": true\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}/trainer-designation") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"designatesTrainer\": true\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and --- ## Update a people flag URL: https://help.skillsdb.com/api-reference/flags/update-a-people-flag Update a people flag cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people-flags/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/{id}" payload = { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'High potential', description: 'Succession candidates.', color: '#F59E0B' }) }; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'High potential', 'description' => 'Succession candidates.', 'color' => '#F59E0B' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/{id}" payload := strings.NewReader("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people-flags/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ --- ## Update a skill flag URL: https://help.skillsdb.com/api-reference/flags/update-a-skill-flag Update a skill flag cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/skill-flags/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "designatesTrainer": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" payload = { "name": "High potential", "description": "Succession candidates.", "color": "#F59E0B", "designatesTrainer": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'High potential', description: 'Succession candidates.', color: '#F59E0B', designatesTrainer: false }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-flags/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'High potential', 'description' => 'Succession candidates.', 'color' => '#F59E0B', 'designatesTrainer' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-flags/{id}" payload := strings.NewReader("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-flags/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"High potential\",\n \"description\": \"Succession candidates.\",\n \"color\": \"#F59E0B\",\n \"designatesTrainer\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "name" : "High potential" , "description" : "Succession candidates." , "color" : "#F59E0B" , "isEnabled" : true , "isSystemDefault" : false , "position" : 2 , "designatesTrainer" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https: --- ## Update the people-flag visibility setting URL: https://help.skillsdb.com/api-reference/flags/update-the-people-flag-visibility-setting Update the people-flag visibility setting cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people-flags/visibility \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "visibleToFullAccess": true, "visibleToManagers": true, "visibleToEmployees": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-flags/visibility" payload = { "visibleToFullAccess": True, "visibleToManagers": True, "visibleToEmployees": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({visibleToFullAccess: true, visibleToManagers: true, visibleToEmployees: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/people-flags/visibility', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-flags/visibility", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'visibleToFullAccess' => true, 'visibleToManagers' => true, 'visibleToEmployees' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-flags/visibility" payload := strings.NewReader("{\n \"visibleToFullAccess\": true,\n \"visibleToManagers\": true,\n \"visibleToEmployees\": false\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people-flags/visibility") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"visibleToFullAccess\": true,\n \"visibleToManagers\": true,\n \"visibleToEmployees\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-flags/visibility") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"visibleToFullAccess\": true,\n \"visibleToManagers\": true,\n \"visibleToEmployees\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "visibleToAdmins": true, "visibleToFullAccess": true, "visibleToManagers": true, "visibleToEmployees": false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be --- ## Add a rung to the grading scale URL: https://help.skillsdb.com/api-reference/grading-scale/add-a-rung-to-the-grading-scale Add a rung to the grading scale cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/grading-scale \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "grade": 3, "label": "Proficient", "description": "Works independently on routine tasks." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale" payload = { "grade": 3, "label": "Proficient", "description": "Works independently on routine tasks." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ grade: 3, label: 'Proficient', description: 'Works independently on routine tasks.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/grading-scale", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'grade' => 3, 'label' => 'Proficient', 'description' => 'Works independently on routine tasks.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/grading-scale" payload := strings.NewReader("{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/grading-scale") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/grading-scale") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "me --- ## Read the company grading scale URL: https://help.skillsdb.com/api-reference/grading-scale/read-the-company-grading-scale Read the company grading scale cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/grading-scale \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/grading-scale", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/grading-scale" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/grading-scale") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/grading-scale") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "7", "grade": 3, "label": "Proficient", "description": "Performs the skill independently in routine situations.", "isActive": true } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / grading-scale Try it Read the company grading scale cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/grading-scale \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/grading-scale", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer --- ## Remove a grading scale rung URL: https://help.skillsdb.com/api-reference/grading-scale/remove-a-grading-scale-rung Remove a grading scale rung cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/grading-scale/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/grading-scale/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/grading-scale/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / grading-scale / {id} Try it Remove a grading scale rung cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/grading-scale/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' \ --header 'Content-Type: application/json' \ --data ' { "grade": 3, "label": "Proficient", "description": "Works independently on routine tasks.", "isActive": true } ' import requests url = "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}" payload = { "grade": 3, "label": "Proficient", "description": "Works independently on routine tasks.", "isActive": True } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ grade: 3, label: 'Proficient', description: 'Works independently on routine tasks.', isActive: true }) }; fetch('https://prod.skillsdbnext.com/api/v1/grading-scale/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'grade' => 3, 'label' => 'Proficient', 'description' => 'Works independently on routine tasks.', 'isActive' => true ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/grading-scale/{id}" payload := strings.NewReader("{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\",\n \"isActive\": true\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/grading-scale/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\",\n \"isActive\": true\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/grading-scale/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"grade\": 3,\n \"label\": \"Proficient\",\n \"description\": \"Works independently on routine tasks.\",\n \"isActive\": true\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "7" , "grade" : 3 , "label" : "Proficient" , "description" : "Performs the skill independently in routine situations." , "isActive" : true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, --- ## Check connectivity URL: https://help.skillsdb.com/api-reference/health/check-connectivity Check connectivity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/ping \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/ping" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/ping', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/ping", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/ping" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/ping") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/ping") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "status" : "ok" , "version" : "v1" , "time" : "2026-08-20T09:12:44.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / ping Try it Check connectivity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/ping \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/ping" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/ping', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/ping", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v --- ## Attach labels to a career URL: https://help.skillsdb.com/api-reference/label/attach-labels-to-a-career Attach labels to a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "li --- ## Attach labels to a certification URL: https://help.skillsdb.com/api-reference/label/attach-labels-to-a-certification Attach labels to a certification cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "t --- ## Attach labels to a learning item URL: https://help.skillsdb.com/api-reference/label/attach-labels-to-a-learning-item Attach labels to a learning item cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "t --- ## Attach labels to a skill URL: https://help.skillsdb.com/api-reference/label/attach-labels-to-a-skill Attach labels to a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must --- ## Create labels URL: https://help.skillsdb.com/api-reference/label/create-labels Create labels cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labels": [ { "name": "Safety", "color": "#D94F4F", "description": "Statutory safety training and licences.", "icon": "shield", "parentId": "4" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/labels" payload = { "labels": [ { "name": "Safety", "color": "#D94F4F", "description": "Statutory safety training and licences.", "icon": "shield", "parentId": "4" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ labels: [ { name: 'Safety', color: '#D94F4F', description: 'Statutory safety training and licences.', icon: 'shield', parentId: '4' } ] }) }; fetch('https://prod.skillsdbnext.com/api/v1/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'labels' => [ [ 'name' => 'Safety', 'color' => '#D94F4F', 'description' => 'Statutory safety training and licences.', 'icon' => 'shield', 'parentId' => '4' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels" payload := strings.NewReader("{\n \"labels\": [\n {\n \"name\": \"Safety\",\n \"color\": \"#D94F4F\",\n \"description\": \"Statutory safety training and licences.\",\n \"icon\": \"shield\",\n \"parentId\": \"4\"\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labels\": [\n {\n \"name\": \"Safety\",\n \"color\": \"#D94F4F\",\n \"description\": \"Statutory safety training and licences.\",\n \"icon\": \"shield\",\n \"parentId\": \"4\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labels\": [\n {\n \"name\": \"Safety\",\n \"color\": \"#D94F4F\",\n \"description\": \"Statutory safety training and licences.\",\n \"icon\": \"shield\",\n \"parentId\": \"4\"\n }\n ]\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instan --- ## Delete a label URL: https://help.skillsdb.com/api-reference/label/delete-a-label Delete a label cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/labels/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/labels/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / {id} Try it Delete a label cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/labels/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/ --- ## Detach labels from a career URL: https://help.skillsdb.com/api-reference/label/detach-labels-from-a-career Detach labels from a career cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 40 --- ## Detach labels from a certification URL: https://help.skillsdb.com/api-reference/label/detach-labels-from-a-certification Detach labels from a certification cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/valid --- ## Detach labels from a learning item URL: https://help.skillsdb.com/api-reference/label/detach-labels-from-a-learning-item Detach labels from a learning item cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/valid --- ## Detach labels from a skill URL: https://help.skillsdb.com/api-reference/label/detach-labels-from-a-skill Detach labels from a skill cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12", "15" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" payload = { "labelIds": ["12", "15"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12', '15']}) }; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12', '15' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\",\n \"15\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "deta --- ## Get a label URL: https://help.skillsdb.com/api-reference/label/get-a-label Get a label cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / {id} Try it Get a label cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = --- ## List a career's labels URL: https://help.skillsdb.com/api-reference/label/list-a-careers-labels List a career's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / labels Try it List a career's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_M --- ## List a certification's labels URL: https://help.skillsdb.com/api-reference/label/list-a-certifications-labels List a certification's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications / {id} / labels Try it List a certification's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api --- ## List a label's children URL: https://help.skillsdb.com/api-reference/label/list-a-labels-children List a label's children cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/{id}/children \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}/children" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}/children', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}/children", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/{id}/children" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels/{id}/children") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/{id}/children") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / {id} / children Try it List a label's children cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/{id}/children \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}/children" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}/children', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}/children", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => --- ## List a learning item's labels URL: https://help.skillsdb.com/api-reference/label/list-a-learning-items-labels List a learning item's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / labels Try it List a learning item's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api --- ## List a skill's labels URL: https://help.skillsdb.com/api-reference/label/list-a-skills-labels List a skill's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / labels Try it List a skill's labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10 --- ## List labels URL: https://help.skillsdb.com/api-reference/label/list-labels List labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels Try it List labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = --- ## List labels as a tree URL: https://help.skillsdb.com/api-reference/label/list-labels-as-a-tree List labels as a tree cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/tree \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/tree" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/tree', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/tree", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/tree" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels/tree") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/tree") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null , "children" : "<array>" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / tree Try it List labels as a tree cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/tree \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/tree" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/tree', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/tree", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION --- ## List labels in use for a kind URL: https://help.skillsdb.com/api-reference/label/list-labels-in-use-for-a-kind List labels in use for a kind cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/in-use \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/in-use" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/in-use', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/in-use", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/in-use" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels/in-use") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/in-use") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / in-use Try it List labels in use for a kind cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/in-use \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/in-use" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/in-use', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/in-use", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HT --- ## List top-level labels URL: https://help.skillsdb.com/api-reference/label/list-top-level-labels List top-level labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/top-level \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/top-level" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/top-level', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/top-level", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/top-level" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/labels/top-level") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/top-level") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / labels / top-level Try it List top-level labels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/labels/top-level \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/top-level" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/labels/top-level', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/top-level", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTT --- ## Reorder labels within a sibling group URL: https://help.skillsdb.com/api-reference/label/reorder-labels-within-a-sibling-group Reorder labels within a sibling group cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/labels/reorder \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "12", "9", "15" ], "parentId": null } ' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/reorder" payload = { "ids": ["12", "9", "15"], "parentId": None } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['12', '9', '15'], parentId: null}) }; fetch('https://prod.skillsdbnext.com/api/v1/labels/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '12', '9', '15' ], 'parentId' => null ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"12\",\n \"9\",\n \"15\"\n ],\n \"parentId\": null\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/labels/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"12\",\n \"9\",\n \"15\"\n ],\n \"parentId\": null\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"12\",\n \"9\",\n \"15\"\n ],\n \"parentId\": null\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data": [ { "id": "12", "name": "Safety", "description": "Statutory safety training and licences.", "icon": "shield", "color": "#D94F4F", "position": 1, "parentId": null, "createdAt": "2026-01-12T08:30:00.000Z", "updatedAt": null } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.s --- ## Reparent a label URL: https://help.skillsdb.com/api-reference/label/reparent-a-label Reparent a label cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/labels/{id}/parent \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "parentId": "4" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}/parent" payload = { "parentId": "4" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({parentId: '4'}) }; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}/parent', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}/parent", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'parentId' => '4' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/{id}/parent" payload := strings.NewReader("{\n \"parentId\": \"4\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/labels/{id}/parent") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"parentId\": \"4\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/{id}/parent") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"parentId\": \"4\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "12", "name": "Safety", "description": "Statutory safety training and licences.", "icon": "shield", "color": "#D94F4F", "position": 1, "parentId": null, "createdAt": "2026-01-12T08:30:00.000Z", "updatedAt": null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "e --- ## Update a label URL: https://help.skillsdb.com/api-reference/label/update-a-label Update a label cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/labels/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Safety & Compliance", "description": null, "icon": "shield-check", "color": "#2E7D32" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/labels/{id}" payload = { "name": "Safety & Compliance", "description": None, "icon": "shield-check", "color": "#2E7D32" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Safety & Compliance', description: null, icon: 'shield-check', color: '#2E7D32' }) }; fetch('https://prod.skillsdbnext.com/api/v1/labels/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/labels/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Safety & Compliance', 'description' => null, 'icon' => 'shield-check', 'color' => '#2E7D32' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/labels/{id}" payload := strings.NewReader("{\n \"name\": \"Safety & Compliance\",\n \"description\": null,\n \"icon\": \"shield-check\",\n \"color\": \"#2E7D32\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/labels/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Safety & Compliance\",\n \"description\": null,\n \"icon\": \"shield-check\",\n \"color\": \"#2E7D32\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/labels/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Safety & Compliance\",\n \"description\": null,\n \"icon\": \"shield-check\",\n \"color\": \"#2E7D32\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "12" , "name" : "Safety" , "description" : "Statutory safety training and licences." , "icon" : "shield" , "color" : "#D94F4F" , "position" : 1 , "parentId" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between --- ## Attach a learning item to a skill URL: https://help.skillsdb.com/api-reference/learning-item/attach-a-learning-item-to-a-skill Attach a learning item to a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillId": "77", "featured": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills" payload = { "skillId": "77", "featured": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillId: '77', featured: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'skillId' => '77', 'featured' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills" payload := strings.NewReader("{\n \"skillId\": \"77\",\n \"featured\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillId\": \"77\",\n \"featured\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillId\": \"77\",\n \"featured\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "featured" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", --- ## Create a learning item URL: https://help.skillsdb.com/api-reference/learning-item/create-a-learning-item Create a learning item cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-items \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "title": "Forklift Safety Refresher", "typeId": "1", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "labelIds": [ "<string>" ], "skillIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items" payload = { "title": "Forklift Safety Refresher", "typeId": "1", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "labelIds": [""], "skillIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ title: 'Forklift Safety Refresher', typeId: '1', description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', labelIds: [''], skillIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'title' => 'Forklift Safety Refresher', 'typeId' => '1', 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'labelIds' => [ '' ], 'skillIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items" payload := strings.NewReader("{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"labelIds\": [\n \"\"\n ],\n \"skillIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-items") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"labelIds\": [\n \"\"\n ],\n \"skillIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"labelIds\": [\n \"\"\n ],\n \"skillIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "title" : "Forklift Safety Refresher" , "description" : "Annual refresher for licensed operators." , "url" : "https://learn.example.com/forklift" , "dur --- ## Create a learning item with a file URL: https://help.skillsdb.com/api-reference/learning-item/create-a-learning-item-with-a-file Create a learning item with a file cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-items/with-file \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "title": "Forklift Safety Refresher", "typeId": "1", "fileName": "forklift-refresher.pdf", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "labelIds": [ "<string>" ], "skillIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/with-file" payload = { "title": "Forklift Safety Refresher", "typeId": "1", "fileName": "forklift-refresher.pdf", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "labelIds": [""], "skillIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ title: 'Forklift Safety Refresher', typeId: '1', fileName: 'forklift-refresher.pdf', description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', labelIds: [''], skillIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/with-file', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/with-file", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'title' => 'Forklift Safety Refresher', 'typeId' => '1', 'fileName' => 'forklift-refresher.pdf', 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'labelIds' => [ '' ], 'skillIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/with-file" payload := strings.NewReader("{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"fileName\": \"forklift-refresher.pdf\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"labelIds\": [\n \"\"\n ],\n \"skillIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-items/with-file") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"fileName\": \"forklift-refresher.pdf\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"labelIds\": [\n \"\"\n ],\n \"skillIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/with-file") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"title\": \"Forklift Safety Refresher\",\n \"typeId\": \"1\",\n \"fileName\": \"forklift-refresher.pdf\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLev --- ## Delete a learning item URL: https://help.skillsdb.com/api-reference/learning-item/delete-a-learning-item Delete a learning item cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} Try it Delete a learning item cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "featured" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / skills / {skillId} Try it Detach a learning item from a skill cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}" headers = {"Authorization": "Bearer "} response = requ --- ## Feature or unfeature a learning item for a skill URL: https://help.skillsdb.com/api-reference/learning-item/feature-or-unfeature-a-learning-item-for-a-skill Feature or unfeature a learning item for a skill cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "featured": true } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}" payload = { "featured": True } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({featured: true}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'featured' => true ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}" payload := strings.NewReader("{\n \"featured\": true\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"featured\": true\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills/{skillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"featured\": true\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "featured" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email --- ## Get a download URL for a learning item's file URL: https://help.skillsdb.com/api-reference/learning-item/get-a-download-url-for-a-learning-items-file Get a download URL for a learning item's file cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "url" : "<string>" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / download-url Try it Get a download URL for a learning item's file cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/download-url", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP --- ## Get a learning item URL: https://help.skillsdb.com/api-reference/learning-item/get-a-learning-item Get a learning item cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "512" , "title" : "Forklift Safety Refresher" , "description" : "Annual refresher for licensed operators." , "url" : "https://learn.example.com/forklift" , "durationHours" : 2.5 , "cost" : 120 , "costDescription" : "Per seat, invoiced quarterly" , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "3" , "name" : "Online course" }, "format" : { "id" : "3" , "name" : "Online course" }, "audience" : { "id" : "3" , "name" : "Online course" }, "courseLevel" : { "id" : "3" , "name" : "Online course" }, "imageUrl" : "https://cdn.example.com/forklift.png" , "hasFile" : true , "referenceId" : "LMS-4471" , "labels" : [ { "id" : "77" , "name" : "Forklift Operation" } ], "skillNames" : [ "Forklift Operation" ], "careerNames" : [ "Warehouse Operator" ], "assignedCount" : 40 , "inProgressCount" : 12 , "completedCount" : 25 , "averageRating" : 1.6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} Try it Get a learning item cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.sk --- ## Get a learning item's rating counts URL: https://help.skillsdb.com/api-reference/learning-item/get-a-learning-items-rating-counts Get a learning item's rating counts cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "thumbsDown" : 2 , "thumbsUp" : 14 , "doubleThumbsUp" : 9 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / ratings Try it Get a learning item's rating counts cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/ratings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", --- ## List a learning item's skills URL: https://help.skillsdb.com/api-reference/learning-item/list-a-learning-items-skills List a learning item's skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "featured" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / skills Try it List a learning item's skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION --- ## List learning items URL: https://help.skillsdb.com/api-reference/learning-item/list-learning-items List learning items cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "512" , "title" : "Forklift Safety Refresher" , "description" : "Annual refresher for licensed operators." , "url" : "https://learn.example.com/forklift" , "durationHours" : 2.5 , "cost" : 120 , "costDescription" : "Per seat, invoiced quarterly" , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "3" , "name" : "Online course" }, "format" : { "id" : "3" , "name" : "Online course" }, "audience" : { "id" : "3" , "name" : "Online course" }, "courseLevel" : { "id" : "3" , "name" : "Online course" }, "imageUrl" : "https://cdn.example.com/forklift.png" , "hasFile" : true , "referenceId" : "LMS-4471" , "labels" : [ { "id" : "77" , "name" : "Forklift Operation" } ], "skillNames" : [ "Forklift Operation" ], "careerNames" : [ "Warehouse Operator" ], "assignedCount" : 40 , "inProgressCount" : 12 , "completedCount" : 25 , "averageRating" : 1.6 , "createdAt" : "2026-01-12T08:30:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items Try it List learning items cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items \ --header 'Authorization: Bearer <token>' import requests url = --- ## List the careers a learning item appears on URL: https://help.skillsdb.com/api-reference/learning-item/list-the-careers-a-learning-item-appears-on List the careers a learning item appears on cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "77", "name": "Forklift Operation" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / careers Try it List the careers a learning item appears on cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/careers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => --- ## Replace a learning item's labels URL: https://help.skillsdb.com/api-reference/learning-item/replace-a-learning-items-labels Replace a learning item's labels cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "labelIds": [ "12" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload = { "labelIds": ["12"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({labelIds: ['12']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'labelIds' => [ '12' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels" payload := strings.NewReader("{\n \"labelIds\": [\n \"12\"\n ]\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"labelIds\": [\n \"12\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/labels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"labelIds\": [\n \"12\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : [ { "id" : "77" , "name" : "Forklift Operation" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or --- ## Update a learning item URL: https://help.skillsdb.com/api-reference/learning-item/update-a-learning-item Update a learning item cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Forklift Safety Refresher (2027)", "typeId": "1" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" payload = { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Forklift Safety Refresher (2027)", "typeId": "1" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', title: 'Forklift Safety Refresher (2027)', typeId: '1' }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'title' => 'Forklift Safety Refresher (2027)', 'typeId' => '1' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}" payload := strings.NewReader("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Forklift Safety Refresher (2027)\",\n \"typeId\": \"1\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Forklift Safety Refresher (2027)\",\n \"typeId\": \"1\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Forklift Safety Refresher (2027)\",\n \"typeId\": \"1\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "title" : "Forklift Safety Refresher" , "description" : "Annual refresher for licensed operators." , "url" : "https://learn.example.com/forklift" , "durationHours" : 2.5 , "cost" : 120 , "costDescription" : "Per seat, invoiced quarterly" , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "3" , "name" : "Online course" }, "format" : { "id" : "3" , "name" : "Online course" }, "audience" : { "id" : "3" , "name" : "Online course" }, "courseLevel" : { "id" : "3" , "name" : "Online course" }, "imageUrl" : "https://cdn.example.com/forklift.png" , "has --- ## Assign learning to people URL: https://help.skillsdb.com/api-reference/learning-plans/assign-learning-to-people Assign learning to people cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "emails": [ "ada@example.com", "grace@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" payload = { "emails": ["ada@example.com", "grace@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({emails: ['ada@example.com', 'grace@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'emails' => [ 'ada@example.com', 'grace@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" payload := strings.NewReader("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "assigned" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1 --- ## Get a learning plan URL: https://help.skillsdb.com/api-reference/learning-plans/get-a-learning-plan Get a learning plan cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-plans/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-plans/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "310" , "personId" : "91" , "learning" : { "id" : "42" , "name" : "Welding" }, "state" : "in_progress" , "dueDate" : "2026-04-01T00:00:00.000Z" , "isPastDue" : false , "dueDateSetById" : "88" , "rating" : "positive" , "careerAssignmentId" : "42" , "assignedAt" : "2026-01-12T08:30:00.000Z" , "startedAt" : null , "completedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-plans / {id} Try it Get a learning plan cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-plans/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-plans/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ --- ## List people assigned to a learning item URL: https://help.skillsdb.com/api-reference/learning-plans/list-people-assigned-to-a-learning-item List people assigned to a learning item cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "42" , "name" : "Welding" }, "planId" : "310" , "state" : "in_progress" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-items / {id} / people Try it List people assigned to a learning item cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => --- ## Rate a learning plan URL: https://help.skillsdb.com/api-reference/learning-plans/rate-a-learning-plan Rate a learning plan cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "rating": "positive" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating" payload = { "rating": "positive" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({rating: 'positive'}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'rating' => 'positive' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating" payload := strings.NewReader("{\n \"rating\": \"positive\"\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"rating\": \"positive\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}/rating") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"rating\": \"positive\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "310" , "personId" : "91" , "learning" : { "id" : "42" , "name" : "Welding" }, "state" : "in_progress" , "dueDate" : "2026-04-01T00:00:00.000Z" , "isPastDue" : false , "dueDateSetById" : "88" , "rating" : "positive" , "careerAssignmentId" : "42" , "assignedAt" : "2026-01-12T08:30:00.000Z" , "startedAt" : null , "completedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limi --- ## Unassign learning from people URL: https://help.skillsdb.com/api-reference/learning-plans/unassign-learning-from-people Unassign learning from people cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "emails": [ "ada@example.com", "grace@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" payload = { "emails": ["ada@example.com", "grace@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({emails: ['ada@example.com', 'grace@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'emails' => [ 'ada@example.com', 'grace@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people" payload := strings.NewReader("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-items/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"emails\": [\n \"ada@example.com\",\n \"grace@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "unassigned" : 2 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", --- ## Update a learning plan URL: https://help.skillsdb.com/api-reference/learning-plans/update-a-learning-plan Update a learning plan cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/learning-plans/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "dueDate": "2026-05-01T00:00:00.000Z" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}" payload = { "dueDate": "2026-05-01T00:00:00.000Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({dueDate: '2026-05-01T00:00:00.000Z'}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-plans/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'dueDate' => '2026-05-01T00:00:00.000Z' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-plans/{id}" payload := strings.NewReader("{\n \"dueDate\": \"2026-05-01T00:00:00.000Z\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"dueDate\": \"2026-05-01T00:00:00.000Z\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-plans/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"dueDate\": \"2026-05-01T00:00:00.000Z\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "310" , "personId" : "91" , "learning" : { "id" : "42" , "name" : "Welding" }, "state" : "in_progress" , "dueDate" : "2026-04-01T00:00:00.000Z" , "isPastDue" : false , "dueDateSetById" : "88" , "rating" : "positive" , "careerAssignmentId" : "42" , "assignedAt" : "2026-01-12T08:30:00.000Z" , "startedAt" : null , "completedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/ --- ## Create a reference entry URL: https://help.skillsdb.com/api-reference/learning-reference-list/create-a-reference-entry Create a reference entry cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Online course", "description": "Self-paced, browser based." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}" payload = { "name": "Online course", "description": "Self-paced, browser based." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Online course', description: 'Self-paced, browser based.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Online course', 'description' => 'Self-paced, browser based.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}" payload := strings.NewReader("{\n \"name\": \"Online course\",\n \"description\": \"Self-paced, browser based.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Online course\",\n \"description\": \"Self-paced, browser based.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Online course\",\n \"description\": \"Self-paced, browser based.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "er --- ## Delete a reference entry URL: https://help.skillsdb.com/api-reference/learning-reference-list/delete-a-reference-entry Delete a reference entry cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-reference / {list} / {id} Try it Delete a reference entry cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{l --- ## Get a reference entry URL: https://help.skillsdb.com/api-reference/learning-reference-list/get-a-reference-entry Get a reference entry cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-reference / {list} / {id} Try it Get a reference entry cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS --- ## List a reference list's entries URL: https://help.skillsdb.com/api-reference/learning-reference-list/list-a-reference-lists-entries List a reference list's entries cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-reference / {list} Try it List a reference list's entries cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENC --- ## List the entries in use URL: https://help.skillsdb.com/api-reference/learning-reference-list/list-the-entries-in-use List the entries in use cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-reference / {list} / in-use Try it List the entries in use cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/in-use', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference --- ## Reorder a reference list URL: https://help.skillsdb.com/api-reference/learning-reference-list/reorder-a-reference-list Reorder a reference list cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "3", "1", "2" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder" payload = { "ids": ["3", "1", "2"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['3', '1', '2']}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '3', '1', '2' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder" payload := strings.NewReader("{\n \"ids\": [\n \"3\",\n \"1\",\n \"2\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"3\",\n \"1\",\n \"2\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/reorder") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"3\",\n \"1\",\n \"2\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data": [ { "id": "3", "name": "Online course", "description": "Self-paced, browser based.", "position": 1, "referenceCount": 14, "createdAt": "2026-01-12T08:30:00.000Z" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error" --- ## Update a reference entry URL: https://help.skillsdb.com/api-reference/learning-reference-list/update-a-reference-entry Update a reference entry cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Online course", "description": "Self-paced." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" payload = { "name": "Online course", "description": "Self-paced." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Online course', description: 'Self-paced.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Online course', 'description' => 'Self-paced.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}" payload := strings.NewReader("{\n \"name\": \"Online course\",\n \"description\": \"Self-paced.\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Online course\",\n \"description\": \"Self-paced.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-reference/{list}/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Online course\",\n \"description\": \"Self-paced.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Online course" , "description" : "Self-paced, browser based." , "position" : 1 , "referenceCount" : 14 , "createdAt" : "2026-01-12T08:30:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com --- ## Approve a learning suggestion URL: https://help.skillsdb.com/api-reference/learning-suggestion/approve-a-learning-suggestion Approve a learning suggestion cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Advanced Rigging (Level 2)", "typeId": "1", "skillIds": [ "" ], "careerIds": [ "" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve" payload = { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Advanced Rigging (Level 2)", "typeId": "1", "skillIds": [""], "careerIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', title: 'Advanced Rigging (Level 2)', typeId: '1', skillIds: [''], careerIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'title' => 'Advanced Rigging (Level 2)', 'typeId' => '1', 'skillIds' => [ '' ], 'careerIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve" payload := strings.NewReader("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/approve") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { --- ## Get a learning suggestion URL: https://help.skillsdb.com/api-reference/learning-suggestion/get-a-learning-suggestion Get a learning suggestion cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id} \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": { "id": "530", "title": "Advanced Rigging", "description": null, "url": "https://learn.example.com/rigging", "durationHours": 8, "cost": 450, "type": { "id": "3", "name": "Online course" }, "provider": { "id": "3", "name": "Online course" }, "format": { "id": "3", "name": "Online course" }, "audience": { "id": "3", "name": "Online course" }, "courseLevel": { "id": "3", "name": "Online course" }, "referenceId": null, "note": "Needed for the crane team.", "suggestedSkillIds": [ "77" ], "suggestedCareerIds": [ "31" ], "status": "pending", "submittedById": "1042", "submittedAt": "2026-03-01T09:00:00.000Z", "approvedById": null, "approvedAt": null, "rejectedById": null, "rejectedAt": null, "rejectionReason": null, "modifiedOnApproval": false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-suggestions / {id} Try it Get a learning suggestion cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id} \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}" headers = {"Authorization": "Bearer "} response = requests.get( --- ## List learning suggestions URL: https://help.skillsdb.com/api-reference/learning-suggestion/list-learning-suggestions List learning suggestions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/learning-suggestions") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "530" , "title" : "Advanced Rigging" , "description" : null , "url" : "https://learn.example.com/rigging" , "durationHours" : 8 , "cost" : 450 , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "3" , "name" : "Online course" }, "format" : { "id" : "3" , "name" : "Online course" }, "audience" : { "id" : "3" , "name" : "Online course" }, "courseLevel" : { "id" : "3" , "name" : "Online course" }, "referenceId" : null , "note" : "Needed for the crane team." , "suggestedSkillIds" : [ "77" ], "suggestedCareerIds" : [ "31" ], "status" : "pending" , "submittedById" : "1042" , "submittedAt" : "2026-03-01T09:00:00.000Z" , "approvedById" : null , "approvedAt" : null , "rejectedById" : null , "rejectedAt" : null , "rejectionReason" : null , "modifiedOnApproval" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / learning-suggestions Try it List learning suggestions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions" headers = {"A --- ## Reject a learning suggestion URL: https://help.skillsdb.com/api-reference/learning-suggestion/reject-a-learning-suggestion Reject a learning suggestion cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "reason": "Already covered by the existing rigging course." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject" payload = { "reason": "Already covered by the existing rigging course." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({reason: 'Already covered by the existing rigging course.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'reason' => 'Already covered by the existing rigging course.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject" payload := strings.NewReader("{\n \"reason\": \"Already covered by the existing rigging course.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"reason\": \"Already covered by the existing rigging course.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}/reject") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"reason\": \"Already covered by the existing rigging course.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "530" , "title" : "Advanced Rigging" , "description" : null , "url" : "https://learn.example.com/rigging" , "durationHours" : 8 , "cost" : 450 , "type" : { "id" : "3" , "name" : "Online course" }, "provider" : { "id" : "3" , "name" : "Online course" }, "format" : { "id" : "3" , "name" : "Online course" }, "audience" : { "id" : "3" , "name" : "Online course" }, "courseLevel" : { "id" : "3" , "name" : "Online course" }, "referenceId" : null , "note" : "Needed for the crane team." , "suggestedSkillIds" : [ "77" ], "suggestedCareerIds" : [ "31" ], "status" : "pending" , "submittedById" : "1042" , "submittedAt" : "2026-03-01T09:00:00.000Z" , "approvedById" : null , "approvedAt" : null , "rejectedById" : null , "rejectedAt" : null , "rejectionReason" : null , "modifiedOnApproval" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ --- ## Revise a pending suggestion URL: https://help.skillsdb.com/api-reference/learning-suggestion/revise-a-pending-suggestion Revise a pending suggestion cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Advanced Rigging (Level 2)", "typeId": "1", "skillIds": [ "<string>" ], "careerIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}" payload = { "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "title": "Advanced Rigging (Level 2)", "typeId": "1", "skillIds": [""], "careerIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', title: 'Advanced Rigging (Level 2)', typeId: '1', skillIds: [''], careerIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'title' => 'Advanced Rigging (Level 2)', 'typeId' => '1', 'skillIds' => [ '' ], 'careerIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}" payload := strings.NewReader("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"title\": \"Advanced Rigging (Level 2)\",\n \"typeId\": \"1\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "530" , "title" : "Advanced Rigging" , "description" : nu --- ## Submit a learning suggestion URL: https://help.skillsdb.com/api-reference/learning-suggestion/submit-a-learning-suggestion Submit a learning suggestion cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/learning-suggestions \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "title": "Advanced Rigging", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "typeId": "1", "note": "Needed for the crane team.", "skillIds": [ "" ], "careerIds": [ "" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions" payload = { "title": "Advanced Rigging", "description": "Annual refresher for licensed operators.", "url": "https://learn.example.com/forklift", "durationHours": 2.5, "cost": 120, "costDescription": "Per seat", "providerId": "3", "formatId": "2", "audienceId": "1", "courseLevelId": "4", "referenceId": "LMS-4471", "typeId": "1", "note": "Needed for the crane team.", "skillIds": [""], "careerIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ title: 'Advanced Rigging', description: 'Annual refresher for licensed operators.', url: 'https://learn.example.com/forklift', durationHours: 2.5, cost: 120, costDescription: 'Per seat', providerId: '3', formatId: '2', audienceId: '1', courseLevelId: '4', referenceId: 'LMS-4471', typeId: '1', note: 'Needed for the crane team.', skillIds: [''], careerIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/learning-suggestions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'title' => 'Advanced Rigging', 'description' => 'Annual refresher for licensed operators.', 'url' => 'https://learn.example.com/forklift', 'durationHours' => 2.5, 'cost' => 120, 'costDescription' => 'Per seat', 'providerId' => '3', 'formatId' => '2', 'audienceId' => '1', 'courseLevelId' => '4', 'referenceId' => 'LMS-4471', 'typeId' => '1', 'note' => 'Needed for the crane team.', 'skillIds' => [ '' ], 'careerIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions" payload := strings.NewReader("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-suggestions") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"\"\n ],\n \"careerIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "peopleCount" : 12 , "personRecordCount" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / {dimension} / {id} / usage Try it Check where a dimension value is used cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/usage", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Auth --- ## Create a dimension value URL: https://help.skillsdb.com/api-reference/org-structure/create-a-dimension-value Create a dimension value cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension} \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Fabrication" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}" payload = { "name": "Fabrication" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Fabrication'}) }; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Fabrication' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}" payload := strings.NewReader("{\n \"name\": \"Fabrication\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/org/{dimension}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Fabrication\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Fabrication\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data": { "id": "4", "name": "Fabrication", "isActive": true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } --- ## Delete a dimension value URL: https://help.skillsdb.com/api-reference/org-structure/delete-a-dimension-value Delete a dimension value cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / {dimension} / {id} Try it Delete a dimension value cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error( --- ## Get the manager tree URL: https://help.skillsdb.com/api-reference/org-structure/get-the-manager-tree Get the manager tree cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/manager-tree \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/manager-tree" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/manager-tree', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/manager-tree", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/manager-tree" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/org/manager-tree") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/manager-tree") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "firstName" : "Dana" , "lastName" : "Reviewer" , "managerId" : "88" , "level" : 0 , "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / manager-tree Try it Get the manager tree cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/manager-tree \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/manager-tree" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/manager-tree', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/manager-tree", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/org/{dimension}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "4" , "name" : "Fabrication" , "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / {dimension} Try it List a dimension's values cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_ --- ## List people by org placement URL: https://help.skillsdb.com/api-reference/org-structure/list-people-by-org-placement List people by org placement cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / {dimension} / {id} / people Try it List people by org placement cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/org/dimensions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/dimensions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/dimensions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/dimensions" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/org/dimensions") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/dimensions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ "businessUnits" ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / org / dimensions Try it List the org dimensions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/org/dimensions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/org/dimensions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/org/dimensions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/dimensions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $e --- ## Update a dimension value URL: https://help.skillsdb.com/api-reference/org-structure/update-a-dimension-value Update a dimension value cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id} \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Fabrication", "isActive": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}" payload = { "name": "Fabrication", "isActive": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Fabrication', isActive: false}) }; fetch('https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Fabrication', 'isActive' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}" payload := strings.NewReader("{\n \"name\": \"Fabrication\",\n \"isActive\": false\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Fabrication\",\n \"isActive\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/org/{dimension}/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Fabrication\",\n \"isActive\": false\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "4", "name": "Fabrication", "isActive": true } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { " --- ## Activate a person URL: https://help.skillsdb.com/api-reference/people/activate-a-person Activate a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/activate \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/activate" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/activate', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/activate", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/activate" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{id}/activate") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/activate") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed" --- ## Attach org schema to a person URL: https://help.skillsdb.com/api-reference/people/attach-org-schema-to-a-person Attach org schema to a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "businessUnitIds": [ "4" ], "divisionIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "countryIds": [ "<string>" ], "stateIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "buildingIds": [ "<string>" ], "departmentIds": [ "<string>" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" payload = { "businessUnitIds": ["4"], "divisionIds": [""], "businessRegionIds": [""], "countryIds": [""], "stateIds": [""], "cityIds": [""], "siteIds": [""], "buildingIds": [""], "departmentIds": [""], "teamIds": [""], "shiftIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ businessUnitIds: ['4'], divisionIds: [''], businessRegionIds: [''], countryIds: [''], stateIds: [''], cityIds: [''], siteIds: [''], buildingIds: [''], departmentIds: [''], teamIds: [''], shiftIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'businessUnitIds' => [ '4' ], 'divisionIds' => [ '' ], 'businessRegionIds' => [ '' ], 'countryIds' => [ '' ], 'stateIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'buildingIds' => [ '' ], 'departmentIds' => [ '' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" payload := strings.NewReader("{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : " --- ## Change a person's email address URL: https://help.skillsdb.com/api-reference/people/change-a-persons-email-address Change a person's email address cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/email \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "email": "dana.new@example.com" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/email" payload = { "email": "dana.new@example.com" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({email: 'dana.new@example.com'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/email', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/email", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'email' => 'dana.new@example.com' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/email" payload := strings.NewReader("{\n \"email\": \"dana.new@example.com\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}/email") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"email\": \"dana.new@example.com\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/email") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"email\": \"dana.new@example.com\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6 --- ## Count people URL: https://help.skillsdb.com/api-reference/people/count-people Count people cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/count \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/count" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/count', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/count", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/count" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/count") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/count") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "total" : 240 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / count Try it Count people cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/count \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/count" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/count', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/count", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https:// --- ## Create a person URL: https://help.skillsdb.com/api-reference/people/create-a-person Create a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "firstName": "Dana", "lastName": "Reviewer", "email": "dana@example.com", "accessLevel": "basic", "externalId": "EMP-0042", "managerEmail": "lead@example.com", "jobTitleId": "12", "peopleTypeId": "3", "countryId": "231", "businessPhone": "+1 555 0100", "mobilePhone": "+1 555 0101", "homePhone": "+1 555 0102", "address": "12 Foundry Rd", "city": "Springfield", "stateProvince": "IL", "postalCode": "62704", "webPage": "https://example.com", "externalCompanyName": "Acme Contracting", "nextAvailableDate": "2026-04-01T00:00:00.000Z", "careerIds": [ "18" ], "learningIds": [ "7" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people" payload = { "firstName": "Dana", "lastName": "Reviewer", "email": "dana@example.com", "accessLevel": "basic", "externalId": "EMP-0042", "managerEmail": "lead@example.com", "jobTitleId": "12", "peopleTypeId": "3", "countryId": "231", "businessPhone": "+1 555 0100", "mobilePhone": "+1 555 0101", "homePhone": "+1 555 0102", "address": "12 Foundry Rd", "city": "Springfield", "stateProvince": "IL", "postalCode": "62704", "webPage": "https://example.com", "externalCompanyName": "Acme Contracting", "nextAvailableDate": "2026-04-01T00:00:00.000Z", "careerIds": ["18"], "learningIds": ["7"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ firstName: 'Dana', lastName: 'Reviewer', email: 'dana@example.com', accessLevel: 'basic', externalId: 'EMP-0042', managerEmail: 'lead@example.com', jobTitleId: '12', peopleTypeId: '3', countryId: '231', businessPhone: '+1 555 0100', mobilePhone: '+1 555 0101', homePhone: '+1 555 0102', address: '12 Foundry Rd', city: 'Springfield', stateProvince: 'IL', postalCode: '62704', webPage: 'https://example.com', externalCompanyName: 'Acme Contracting', nextAvailableDate: '2026-04-01T00:00:00.000Z', careerIds: ['18'], learningIds: ['7'] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'firstName' => 'Dana', 'lastName' => 'Reviewer', 'email' => 'dana@example.com', 'accessLevel' => 'basic', 'externalId' => 'EMP-0042', 'managerEmail' => 'lead@example.com', 'jobTitleId' => '12', 'peopleTypeId' => '3', 'countryId' => '231', 'businessPhone' => '+1 555 0100', 'mobilePhone' => '+1 555 0101', 'homePhone' => '+1 555 0102', 'address' => '12 Foundry Rd', 'city' => 'Springfield', 'stateProvince' => 'IL', 'postalCode' => '62704', 'webPage' => 'https://example.com', 'externalCompanyName' => 'Acme Contracting', 'nextAvailableDate' => '2026-04-01T00:00:00.000Z', 'careerIds' => [ '18' ], 'learningIds' => [ '7' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people" payload := strings.NewReader("{\n \"firstName\": \"Dana\",\n \"lastName\": \"Reviewer\",\n \"email\": \"dana@example.com\",\n \"accessLevel\": \"basic\",\n \"externalId\": \"EMP-0042\",\n \"managerEmail\": \"lead@example.com\",\n \"jobTitleId\": \"12\",\n \"peopleTypeId\": \"3\",\n \"countryId\": \"231\",\n \"businessPhone\": \"+1 555 0100\",\n \"mobilePhone\": \"+1 555 0101\",\n \"homePhone\": \"+1 555 0102\",\n \"address\": \"12 Foundry Rd\",\n \"city\": \"Springfield\",\n \"stateProvince\": \"IL\",\n \"postalCode\": \"62704\",\n \"webPage\": \"https://example.com\",\n \"externalCompanyName\": \"Acme Contracting\",\n \"nextAvailableDate\": \"2026-04-01T00:00:00.000Z\",\n \"careerIds\": [\n \"18\"\n ],\n \"learningIds\": [\n \"7\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"firstName\": \"Dana\",\n \"lastName\": \"Reviewer\",\n \"email\": \"dana@example.com\",\n \"accessLevel\": \"basic\",\n \"externalId\": \"EMP-0042\",\n \"managerEmail\": \"lead@example.com\",\n \"jobTitleId\": \"12\",\n \"peopleTypeId\": \"3\",\n \"countryId\": \"231\",\n \"businessPhone\": \"+1 555 0100\",\n \"mobilePhone\": \"+1 555 0101\",\n --- ## Deactivate a person URL: https://help.skillsdb.com/api-reference/people/deactivate-a-person Deactivate a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/deactivate") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Va --- ## Detach org schema from a person URL: https://help.skillsdb.com/api-reference/people/detach-org-schema-from-a-person Detach org schema from a person cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "businessUnitIds": [ "4" ], "divisionIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "countryIds": [ "<string>" ], "stateIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "buildingIds": [ "<string>" ], "departmentIds": [ "<string>" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" payload = { "businessUnitIds": ["4"], "divisionIds": [""], "businessRegionIds": [""], "countryIds": [""], "stateIds": [""], "cityIds": [""], "siteIds": [""], "buildingIds": [""], "departmentIds": [""], "teamIds": [""], "shiftIds": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ businessUnitIds: ['4'], divisionIds: [''], businessRegionIds: [''], countryIds: [''], stateIds: [''], cityIds: [''], siteIds: [''], buildingIds: [''], departmentIds: [''], teamIds: [''], shiftIds: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'businessUnitIds' => [ '4' ], 'divisionIds' => [ '' ], 'businessRegionIds' => [ '' ], 'countryIds' => [ '' ], 'stateIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'buildingIds' => [ '' ], 'departmentIds' => [ '' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" payload := strings.NewReader("{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"businessUnitIds\": [\n \"4\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"stateIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"buildingIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments --- ## Get a person URL: https://help.skillsdb.com/api-reference/people/get-a-person Get a person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api --- ## Get a person's avatar URL: https://help.skillsdb.com/api-reference/people/get-a-persons-avatar Get a person's avatar cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/avatar \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/avatar" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/avatar', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/avatar", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/avatar" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{id}/avatar") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/avatar") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "url" : "https://storage.example.com/avatars/91.png?sig=..." } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {id} / avatar Try it Get a person's avatar cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/avatar \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/avatar" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/avatar', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/avatar", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($cu --- ## Get a person's org schema URL: https://help.skillsdb.com/api-reference/people/get-a-persons-org-schema Get a person's org schema cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {id} / org-schema Try it Get a person's org schema cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://pr --- ## Get reporting-structure distribution URL: https://help.skillsdb.com/api-reference/people/get-reporting-structure-distribution Get reporting-structure distribution cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/distribution \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/distribution" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/distribution', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/distribution", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/distribution" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/distribution") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/distribution") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": { "byAccessLevel": [ { "accessLevel": { "slug": "admin", "name": "Admin", "isAssignable": true }, "peopleCount": 120 } ], "byManager": [ { "manager": { "id": "42", "name": "Welding" }, "peopleCount": 8 } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / distribution Try it Get reporting-structure distribution cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/distribution \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/distribution" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/distribution', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/distribution", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_H --- ## List a person's direct reports URL: https://help.skillsdb.com/api-reference/people/list-a-persons-direct-reports List a person's direct reports cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {id} / direct-reports Try it List a person's direct reports cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/direct-reports', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "level" : 0 } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {id} / span-of-control Try it List a person's span of control cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/span-of-control', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/managers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/managers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/managers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/managers" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/managers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/managers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / managers Try it List managers and above cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/managers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/managers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/managers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/managers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOP --- ## List people URL: https://help.skillsdb.com/api-reference/people/list-people List people cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people Try it List people cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization --- ## Replace a person's org schema in one dimension URL: https://help.skillsdb.com/api-reference/people/replace-a-persons-org-schema-in-one-dimension Replace a person's org schema in one dimension cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "ids": [ "4", "9" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}" payload = { "ids": ["4", "9"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ids: ['4', '9']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'ids' => [ '4', '9' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}" payload := strings.NewReader("{\n \"ids\": [\n \"4\",\n \"9\"\n ]\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"ids\": [\n \"4\",\n \"9\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/org-schema/{dimension}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"ids\": [\n \"4\",\n \"9\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "request --- ## Set a person's access level URL: https://help.skillsdb.com/api-reference/people/set-a-persons-access-level Set a person's access level cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/access-level \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "accessLevel": "manager" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/access-level" payload = { "accessLevel": "manager" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({accessLevel: 'manager'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/access-level', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/access-level", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'accessLevel' => 'manager' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/access-level" payload := strings.NewReader("{\n \"accessLevel\": \"manager\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}/access-level") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"accessLevel\": \"manager\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/access-level") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"accessLevel\": \"manager\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e- --- ## Set a person's job title URL: https://help.skillsdb.com/api-reference/people/set-a-persons-job-title Set a person's job title cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/job-title \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "jobTitleId": "12" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/job-title" payload = { "jobTitleId": "12" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({jobTitleId: '12'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/job-title', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/job-title", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'jobTitleId' => '12' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/job-title" payload := strings.NewReader("{\n \"jobTitleId\": \"12\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}/job-title") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"jobTitleId\": \"12\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/job-title") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"jobTitleId\": \"12\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": " --- ## Set a person's manager URL: https://help.skillsdb.com/api-reference/people/set-a-persons-manager Set a person's manager cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/manager \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "email": "lead@example.com" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/manager" payload = { "email": "lead@example.com" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({email: 'lead@example.com'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/manager', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/manager", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'email' => 'lead@example.com' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/manager" payload := strings.NewReader("{\n \"email\": \"lead@example.com\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}/manager") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"email\": \"lead@example.com\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/manager") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"email\": \"lead@example.com\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "91", "externalId": "EMP-0042", "firstName": "Dana", "lastName": "Reviewer", "email": "dana@example.com", "accessLevel": { "slug": "admin", "name": "Admin", "isAssignable": true }, "manager": { "id": "42", "name": "Welding" }, "isActive": true, "jobTitle": { "id": "42", "name": "Welding" }, "peopleType": { "id": "42", "name": "Welding", "expiresAt": "2026-12-31T00:00:00.000Z" }, "orgSchema": { "businessUnits": [ { "id": "42", "name": "Welding" } ], "divisions": [ { "id": "42", "name": "Welding" } ], "businessRegions": [ { "id": "42", "name": "Welding" } ], "countries": [ { "id": "42", "name": "Welding" } ], "states": [ { "id": "42", "name": "Welding" } ], "cities": [ { "id": "42", "name": "Welding" } ], "sites": [ { "id": "42", "name": "Welding" } ], "buildings": [ { "id": "42", "name": "Welding" } ], "departments": [ { "id": "42", "name": "Welding" } ], "teams": [ { "id": "42", "name": "Welding" } ], "shifts": [ { "id": "42", "name": "Welding" } ] }, "businessPhone": "+1 555 0100", "mobilePhone": "+1 555 0101", "homePhone": "+1 555 0102", "address": "12 Foundry Rd", "city": "Springfield", "stateProvince": "IL", "postalCode": "62704", "country": { "id": "42", "name": "Welding" }, "webPage": "https://example.com", "externalCompanyName": "Acme Contracting", "nextAvailableDate": "2026-04-01T00:00:00.000Z", "inactiveAt": null, "createdAt": "2026-01-12T08:30:00.000Z", "createdById": "88", "updatedAt": "2026-03-02T14:00:00.000Z", "updatedById": "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be --- ## Set a person's people type URL: https://help.skillsdb.com/api-reference/people/set-a-persons-people-type Set a person's people type cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id}/people-type \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "peopleTypeId": "3", "expiresAt": "2026-12-31T00:00:00.000Z" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}/people-type" payload = { "peopleTypeId": "3", "expiresAt": "2026-12-31T00:00:00.000Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({peopleTypeId: '3', expiresAt: '2026-12-31T00:00:00.000Z'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}/people-type', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}/people-type", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'peopleTypeId' => '3', 'expiresAt' => '2026-12-31T00:00:00.000Z' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}/people-type" payload := strings.NewReader("{\n \"peopleTypeId\": \"3\",\n \"expiresAt\": \"2026-12-31T00:00:00.000Z\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}/people-type") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"peopleTypeId\": \"3\",\n \"expiresAt\": \"2026-12-31T00:00:00.000Z\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}/people-type") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"peopleTypeId\": \"3\",\n \"expiresAt\": \"2026-12-31T00:00:00.000Z\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "91" , "externalId" : "EMP-0042" , "firstName" : "Dana" , "lastName" : "Reviewer" , "email" : "dana@example.com" , "accessLevel" : { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true }, "manager" : { "id" : "42" , "name" : "Welding" }, "isActive" : true , "jobTitle" : { "id" : "42" , "name" : "Welding" }, "peopleType" : { "id" : "42" , "name" : "Welding" , "expiresAt" : "2026-12-31T00:00:00.000Z" }, "orgSchema" : { "businessUnits" : [ { "id" : "42" , "name" : "Welding" } ], "divisions" : [ { "id" : "42" , "name" : "Welding" } ], "businessRegions" : [ { "id" : "42" , "name" : "Welding" } ], "countries" : [ { "id" : "42" , "name" : "Welding" } ], "states" : [ { "id" : "42" , "name" : "Welding" } ], "cities" : [ { "id" : "42" , "name" : "Welding" } ], "sites" : [ { "id" : "42" , "name" : "Welding" } ], "buildings" : [ { "id" : "42" , "name" : "Welding" } ], "departments" : [ { "id" : "42" , "name" : "Welding" } ], "teams" : [ { "id" : "42" , "name" : "Welding" } ], "shifts" : [ { "id" : "42" , "name" : "Welding" } ] }, "businessPhone" : "+1 555 0100" , "mobilePhone" : "+1 555 0101" , "homePhone" : "+1 555 0102" , "address" : "12 Foundry Rd" , "city" : "Springfield" , "stateProvince" : "IL" , "postalCode" : "62704" , "country" : { "id" : "42" , "name" : "Welding" }, "webPage" : "https://example.com" , "externalCompanyName" : "Acme Contracting" , "nextAvailableDate" : "2026-04-01T00:00:00.000Z" , "inactiveAt" : null , "createdAt" : "2026-01-12T08:30:00.000Z" , "createdById" : "88" , "updatedAt" : "2026-03-02T14:00:00.000Z" , "updatedById" : "88" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial --- ## Update a person URL: https://help.skillsdb.com/api-reference/people/update-a-person Update a person cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{id} \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "firstName": "Dana", "lastName": "Reviewer", "externalId": "EMP-0042", "businessPhone": "", "mobilePhone": "", "homePhone": "", "address": "", "city": "", "stateProvince": "", "postalCode": "", "countryId": "", "webPage": "", "externalCompanyName": "", "nextAvailableDate": "" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{id}" payload = { "firstName": "Dana", "lastName": "Reviewer", "externalId": "EMP-0042", "businessPhone": "", "mobilePhone": "", "homePhone": "", "address": "", "city": "", "stateProvince": "", "postalCode": "", "countryId": "", "webPage": "", "externalCompanyName": "", "nextAvailableDate": "" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ firstName: 'Dana', lastName: 'Reviewer', externalId: 'EMP-0042', businessPhone: '', mobilePhone: '', homePhone: '', address: '', city: '', stateProvince: '', postalCode: '', countryId: '', webPage: '', externalCompanyName: '', nextAvailableDate: '' }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'firstName' => 'Dana', 'lastName' => 'Reviewer', 'externalId' => 'EMP-0042', 'businessPhone' => '', 'mobilePhone' => '', 'homePhone' => '', 'address' => '', 'city' => '', 'stateProvince' => '', 'postalCode' => '', 'countryId' => '', 'webPage' => '', 'externalCompanyName' => '', 'nextAvailableDate' => '' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{id}" payload := strings.NewReader("{\n \"firstName\": \"Dana\",\n \"lastName\": \"Reviewer\",\n \"externalId\": \"EMP-0042\",\n \"businessPhone\": \"\",\n \"mobilePhone\": \"\",\n \"homePhone\": \"\",\n \"address\": \"\",\n \"city\": \"\",\n \"stateProvince\": \"\",\n \"postalCode\": \"\",\n \"countryId\": \"\",\n \"webPage\": \"\",\n \"externalCompanyName\": \"\",\n \"nextAvailableDate\": \"\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"firstName\": \"Dana\",\n \"lastName\": \"Reviewer\",\n \"externalId\": \"EMP-0042\",\n \"businessPhone\": \"\",\n \"mobilePhone\": \"\",\n \"homePhone\": \"\",\n \"address\": \"\",\n \"city\": \"\",\n \"stateProvince\": \"\",\n \"postalCode\": \"\",\n \"countryId\": \"\",\n \"webPage\": \"\",\n \"externalCompanyName\": \"\",\n \"nextAvailableDate\": \"\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"firstName\": \"Dana\",\n \"lastName\": \"Reviewer\",\n \"externalId\": \"EMP-0042\",\n \"businessPhone\": \"\",\n \"mobilePhone\": \"\",\n \"homePhone\": \"\",\n \"address\": \"\",\n \"city\": \"\",\n \"stateProvince\": \"\",\n \"postalCode\": \"\",\n \"countryId\": \"\",\n \"webPage\": \"\",\n \"externalCompanyName\": \"\",\n \"nextAvailableDate\": \"\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "91", "externalId": "EMP-0042", "firstName": "Dana", "lastName": "Reviewer", "email": "dana@example.com", "accessLevel": { "slug": "admin", "name": "Admin", "isAssignable": true }, "manager": { "id": "42", "name": "Welding" }, "isActive": true, "jobTi --- ## Create a job title URL: https://help.skillsdb.com/api-reference/person-attributes/create-a-job-title Create a job title cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/job-titles \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Fabricator" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles" payload = { "name": "Fabricator" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Fabricator'}) }; fetch('https://prod.skillsdbnext.com/api/v1/job-titles', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Fabricator' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/job-titles" payload := strings.NewReader("{\n \"name\": \"Fabricator\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/job-titles") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Fabricator\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/job-titles") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Fabricator\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "12" , "name" : "Fabricator" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / job-ti --- ## Create a people type URL: https://help.skillsdb.com/api-reference/person-attributes/create-a-people-type Create a people type cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-types \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Contractor" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types" payload = { "name": "Contractor" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Contractor'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Contractor' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-types" payload := strings.NewReader("{\n \"name\": \"Contractor\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-types") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Contractor\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Contractor\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Contractor" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / ap --- ## Delete a job title URL: https://help.skillsdb.com/api-reference/person-attributes/delete-a-job-title Delete a job title cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/job-titles/{id} \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / job-titles / {id} Try it Delete a job title cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/job-titles/{id} \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "htt --- ## Delete a people type URL: https://help.skillsdb.com/api-reference/person-attributes/delete-a-people-type Delete a people type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-types/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people-types/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-types / {id} Try it Delete a people type cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people-types/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": { "id": "12", "name": "Fabricator" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / job-titles / {id} Try it Get a job title cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/job-titles/{id} \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } packag --- ## List access levels URL: https://help.skillsdb.com/api-reference/person-attributes/list-access-levels List access levels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/access-levels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/access-levels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/access-levels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/access-levels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/access-levels" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/access-levels") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/access-levels") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "slug" : "admin" , "name" : "Admin" , "isAssignable" : true } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / access-levels Try it List access levels cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/access-levels \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/access-levels" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/access-levels', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/access-levels", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { e --- ## List countries URL: https://help.skillsdb.com/api-reference/person-attributes/list-countries List countries cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/countries \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/countries" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/countries', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/countries", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/countries" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/countries") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/countries") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "231" , "name" : "United States" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / countries Try it List countries cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/countries \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/countries" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/countries', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/countries", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( --- ## List job titles URL: https://help.skillsdb.com/api-reference/person-attributes/list-job-titles List job titles cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/job-titles \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/job-titles" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/job-titles") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/job-titles") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "12" , "name" : "Fabricator" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / job-titles Try it List job titles cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/job-titles \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/job-titles', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package mai --- ## List people types URL: https://help.skillsdb.com/api-reference/person-attributes/list-people-types List people types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-types \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-types" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-types") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-types") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "3", "name": "Contractor" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-types Try it List people types cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-types \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-types', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-types", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { ec --- ## Update a job title URL: https://help.skillsdb.com/api-reference/person-attributes/update-a-job-title Update a job title cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/job-titles/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Fabricator" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" payload = { "name": "Fabricator" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Fabricator'}) }; fetch('https://prod.skillsdbnext.com/api/v1/job-titles/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/job-titles/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Fabricator' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/job-titles/{id}" payload := strings.NewReader("{\n \"name\": \"Fabricator\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Fabricator\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/job-titles/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Fabricator\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "12" , "name" : "Fabricator" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } PATCH https://prod.skillsdbnext.com https://s --- ## Update a people type URL: https://help.skillsdb.com/api-reference/person-attributes/update-a-people-type Update a people type cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people-types/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Contractor" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-types/{id}" payload = { "name": "Contractor" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Contractor'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people-types/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-types/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Contractor' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-types/{id}" payload := strings.NewReader("{\n \"name\": \"Contractor\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people-types/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Contractor\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-types/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Contractor\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "3" , "name" : "Contractor" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } PATCH https://prod.skillsdbnex --- ## Approve a certification URL: https://help.skillsdb.com/api-reference/person-certification/approve-a-certification Approve a certification cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/approve") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title --- ## Certification coverage across a scope URL: https://help.skillsdb.com/api-reference/person-certification/certification-coverage-across-a-scope Certification coverage across a scope cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-coverage \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-coverage" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certification-coverage', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certification-coverage", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certification-coverage" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certification-coverage") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certification-coverage") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certification-coverage Try it Certification coverage across a scope cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certification-coverage \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certification-coverage" headers = {"Authorization": "Bearer "} response = requests.g --- ## Decide many certifications at once URL: https://help.skillsdb.com/api-reference/person-certification/decide-many-certifications-at-once Decide many certifications at once cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-certifications/decisions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "decision": "approve", "items": [ { "email": "ada@example.com", "certificationId": "87" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-certifications/decisions" payload = { "decision": "approve", "items": [ { "email": "ada@example.com", "certificationId": "87" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ decision: 'approve', items: [{email: 'ada@example.com', certificationId: '87'}] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people-certifications/decisions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-certifications/decisions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'decision' => 'approve', 'items' => [ [ 'email' => 'ada@example.com', 'certificationId' => '87' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-certifications/decisions" payload := strings.NewReader("{\n \"decision\": \"approve\",\n \"items\": [\n {\n \"email\": \"ada@example.com\",\n \"certificationId\": \"87\"\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-certifications/decisions") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"decision\": \"approve\",\n \"items\": [\n {\n \"email\": \"ada@example.com\",\n \"certificationId\": \"87\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-certifications/decisions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"decision\": \"approve\",\n \"items\": [\n {\n \"email\": \"ada@example.com\",\n \"certificationId\": \"87\"\n }\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "applied" : 4 , "failed" : 1 , "outcomes" : [ { "email" : "ada@example.com" , "certificationId" : "87" , "outcome" : "applied" , "error" : null } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation fa --- ## Deny a certification URL: https://help.skillsdb.com/api-reference/person-certification/deny-a-certification Deny a certification cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/deny") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", --- ## Get a certification's status breakdown URL: https://help.skillsdb.com/api-reference/person-certification/get-a-certifications-status-breakdown Get a certification's status breakdown cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "certificationId" : "87" , "holders" : 46 , "byStatus" : { "assigned" : 3 , "awaitingApproval" : 2 , "approved" : 40 , "denied" : 1 , "unknown" : 0 }, "expiringWithinDays" : 30 , "expiry" : { "expired" : 4 , "expiringSoon" : 6 , "valid" : 30 , "none" : 6 } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications / {id} / status-breakdown Try it Get a certification's status breakdown cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/status-breakdown', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": { "url": "" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications / {certificationId} / attachments / {attachmentId} / download-url Try it Get a download URL for an attachment cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) co --- ## Get one of a person's certifications URL: https://help.skillsdb.com/api-reference/person-certification/get-one-of-a-persons-certifications Get one of a person's certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications / {certifi --- ## List a person's certification history URL: https://help.skillsdb.com/api-reference/person-certification/list-a-persons-certification-history List a person's certification history cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/history") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "301", "endedAs": "expired", "issuedAt": "2023-06-01T00:00:00.000Z", "expiresAt": "2025-06-01T00:00:00.000Z", "identifier": "FL-2291-A", "scoreDescription": "Pass", "archivedAt": "2026-01-12T10:00:00.000Z", "archivedById": "1001", "assignedAt": "2023-05-20T10:00:00.000Z", "assignedById": "1001", "submittedAt": "2023-05-28T10:00:00.000Z", "submittedById": "1042", "approvedAt": "2023-06-02T10:00:00.000Z", "approvedById": "1001", "deniedAt": null, "deniedById": null, "attachments": [ { "id": "5011", "type": "file", "label": "Certificate scan", "url": "https://verify.example.org/abc", "createdAt": "2026-02-01T09:00:00.000Z" } ] } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications / {certificationId} / history Try it List a person's certification history cURL curl --request GET \ --url https://prod.skills --- ## List a person's certifications URL: https://help.skillsdb.com/api-reference/person-certification/list-a-persons-certifications List a person's certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications Try it List a person's certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/p --- ## List certifications available to a person URL: https://help.skillsdb.com/api-reference/person-certification/list-certifications-available-to-a-person List certifications available to a person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "88" , "name" : "First Aid" , "description" : "Workplace first aid." , "issuingAuthorityName" : "Red Cross" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / available-certifications Try it List certifications available to a person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/available-certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/certifications/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/certifications/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/certifications/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/certifications/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/certifications/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / certifications / {id} / people Try it List people holding a certification cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/certifications/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/certifications/{id}/people" headers = {"Authorization": --- ## Record a certification by external key URL: https://help.skillsdb.com/api-reference/person-certification/record-a-certification-by-external-key Record a certification by external key cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people-certifications/composite \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "email": "ada@example.com", "issuedAt": "2026-01-15", "certificationTitle": "Forklift Operator Licence", "certificationId": "87", "expiresAt": "2028-01-15", "scoreDescription": "Pass", "renew": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people-certifications/composite" payload = { "email": "ada@example.com", "issuedAt": "2026-01-15", "certificationTitle": "Forklift Operator Licence", "certificationId": "87", "expiresAt": "2028-01-15", "scoreDescription": "Pass", "renew": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ email: 'ada@example.com', issuedAt: '2026-01-15', certificationTitle: 'Forklift Operator Licence', certificationId: '87', expiresAt: '2028-01-15', scoreDescription: 'Pass', renew: false }) }; fetch('https://prod.skillsdbnext.com/api/v1/people-certifications/composite', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-certifications/composite", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'email' => 'ada@example.com', 'issuedAt' => '2026-01-15', 'certificationTitle' => 'Forklift Operator Licence', 'certificationId' => '87', 'expiresAt' => '2028-01-15', 'scoreDescription' => 'Pass', 'renew' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-certifications/composite" payload := strings.NewReader("{\n \"email\": \"ada@example.com\",\n \"issuedAt\": \"2026-01-15\",\n \"certificationTitle\": \"Forklift Operator Licence\",\n \"certificationId\": \"87\",\n \"expiresAt\": \"2028-01-15\",\n \"scoreDescription\": \"Pass\",\n \"renew\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people-certifications/composite") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"email\": \"ada@example.com\",\n \"issuedAt\": \"2026-01-15\",\n \"certificationTitle\": \"Forklift Operator Licence\",\n \"certificationId\": \"87\",\n \"expiresAt\": \"2028-01-15\",\n \"scoreDescription\": \"Pass\",\n \"renew\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-certifications/composite") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"email\": \"ada@example.com\",\n \"issuedAt\": \"2026-01-15\",\n \"certificationTitle\": \"Forklift Operator Licence\",\n \"certificationId\": \"87\",\n \"expiresAt\": \"2028-01-15\",\n \"scoreDescription\": \"Pass\",\n \"renew\": false\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 422 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", " --- ## Record a certification for a person URL: https://help.skillsdb.com/api-reference/person-certification/record-a-certification-for-a-person Record a certification for a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "certificationId": "87", "issuedAt": "2025-06-01", "expiresAt": "2027-06-01", "identifier": "FL-2291-B", "scoreDescription": "Distinction", "certified": true, "issuingAuthority": "National Safety Council", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications" payload = { "certificationId": "87", "issuedAt": "2025-06-01", "expiresAt": "2027-06-01", "identifier": "FL-2291-B", "scoreDescription": "Distinction", "certified": True, "issuingAuthority": "National Safety Council", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ certificationId: '87', issuedAt: '2025-06-01', expiresAt: '2027-06-01', identifier: 'FL-2291-B', scoreDescription: 'Distinction', certified: true, issuingAuthority: 'National Safety Council', files: [{fileName: 'certificate.pdf', label: 'Certificate scan'}] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'certificationId' => '87', 'issuedAt' => '2025-06-01', 'expiresAt' => '2027-06-01', 'identifier' => 'FL-2291-B', 'scoreDescription' => 'Distinction', 'certified' => true, 'issuingAuthority' => 'National Safety Council', 'files' => [ [ 'fileName' => 'certificate.pdf', 'label' => 'Certificate scan' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications" payload := strings.NewReader("{\n \"certificationId\": \"87\",\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"certificationId\": \"87\",\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"certificationId\": \"87\",\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "certification" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] }, "uploads" : [ { "attachmentId" : --- ## Remove a certification attachment URL: https://help.skillsdb.com/api-reference/person-certification/remove-a-certification-attachment Remove a certification attachment cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications / {certificationId} / attachments / {attachmentId} Try it Remove a certification attachment cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attach --- ## Renew a certification URL: https://help.skillsdb.com/api-reference/person-certification/renew-a-certification Renew a certification cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "issuedAt": "2027-06-01", "expiresAt": "2029-06-01", "identifier": "FL-2291-C", "scoreDescription": "Pass", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew" payload = { "issuedAt": "2027-06-01", "expiresAt": "2029-06-01", "identifier": "FL-2291-C", "scoreDescription": "Pass", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ issuedAt: '2027-06-01', expiresAt: '2029-06-01', identifier: 'FL-2291-C', scoreDescription: 'Pass', files: [{fileName: 'certificate.pdf', label: 'Certificate scan'}] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'issuedAt' => '2027-06-01', 'expiresAt' => '2029-06-01', 'identifier' => 'FL-2291-C', 'scoreDescription' => 'Pass', 'files' => [ [ 'fileName' => 'certificate.pdf', 'label' => 'Certificate scan' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew" payload := strings.NewReader("{\n \"issuedAt\": \"2027-06-01\",\n \"expiresAt\": \"2029-06-01\",\n \"identifier\": \"FL-2291-C\",\n \"scoreDescription\": \"Pass\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"issuedAt\": \"2027-06-01\",\n \"expiresAt\": \"2029-06-01\",\n \"identifier\": \"FL-2291-C\",\n \"scoreDescription\": \"Pass\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/renew") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"issuedAt\": \"2027-06-01\",\n \"expiresAt\": \"2029-06-01\",\n \"identifier\": \"FL-2291-C\",\n \"scoreDescription\": \"Pass\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "certification" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] }, "uploads" : [ { "attachmentId" : "5011" , "fileName" : "certificate.pdf" , "label" : "Certificate scan" , "uploadUrl" : "<string>" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": --- ## Search people's certifications URL: https://help.skillsdb.com/api-reference/person-certification/search-peoples-certifications Search people's certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people-certifications', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people-certifications", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people-certifications" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people-certifications") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people-certifications") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people-certifications Try it Search people's certifications cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people-certifications \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people-certifications" headers = {"Authorization": "Bearer "} response = requests.get(url, header --- ## Submit a certification for approval URL: https://help.skillsdb.com/api-reference/person-certification/submit-a-certification-for-approval Submit a certification for approval cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/submit") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", " --- ## Unassign a certification URL: https://help.skillsdb.com/api-reference/person-certification/unassign-a-certification Unassign a certification cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / certifications / {certificationId} Try it Unassign a certification cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, header --- ## Update a certification attachment URL: https://help.skillsdb.com/api-reference/person-certification/update-a-certification-attachment Update a certification attachment cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "label": "Certificate scan (2027)" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}" payload = { "label": "Certificate scan (2027)" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({label: 'Certificate scan (2027)'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'label' => 'Certificate scan (2027)' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}" payload := strings.NewReader("{\n \"label\": \"Certificate scan (2027)\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"label\": \"Certificate scan (2027)\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}/attachments/{attachmentId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"label\": \"Certificate scan (2027)\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skil --- ## Update a person's certification URL: https://help.skillsdb.com/api-reference/person-certification/update-a-persons-certification Update a person's certification cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "issuedAt": "2025-06-01", "expiresAt": "2027-06-01", "identifier": "FL-2291-B", "scoreDescription": "Distinction", "certified": true, "issuingAuthority": "National Safety Council", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" payload = { "issuedAt": "2025-06-01", "expiresAt": "2027-06-01", "identifier": "FL-2291-B", "scoreDescription": "Distinction", "certified": True, "issuingAuthority": "National Safety Council", "files": [ { "fileName": "certificate.pdf", "label": "Certificate scan" } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ issuedAt: '2025-06-01', expiresAt: '2027-06-01', identifier: 'FL-2291-B', scoreDescription: 'Distinction', certified: true, issuingAuthority: 'National Safety Council', files: [{fileName: 'certificate.pdf', label: 'Certificate scan'}] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'issuedAt' => '2025-06-01', 'expiresAt' => '2027-06-01', 'identifier' => 'FL-2291-B', 'scoreDescription' => 'Distinction', 'certified' => true, 'issuingAuthority' => 'National Safety Council', 'files' => [ [ 'fileName' => 'certificate.pdf', 'label' => 'Certificate scan' ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}" payload := strings.NewReader("{\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/certifications/{certificationId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"issuedAt\": \"2025-06-01\",\n \"expiresAt\": \"2027-06-01\",\n \"identifier\": \"FL-2291-B\",\n \"scoreDescription\": \"Distinction\",\n \"certified\": true,\n \"issuingAuthority\": \"National Safety Council\",\n \"files\": [\n {\n \"fileName\": \"certificate.pdf\",\n \"label\": \"Certificate scan\"\n }\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "certification" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "certification" : { "id" : "87" , "name" : "Forklift Operator Licence" , "type" : "Regulatory" }, "status" : "approved" , "certified" : true , "identifier" : "FL-2291-B" , "issuedAt" : "2025-06-01T00:00:00.000Z" , "expiresAt" : "2027-06-01T00:00:00.000Z" , "expiry" : { "state" : "expiring" , "daysUntil" : 12 }, "scoreDescription" : "Distinction" , "issuingAuthority" : "National Safety Council" , "heldDirectly" : true , "careers" : [ "Warehouse Operator" ], "attachmentCount" : 2 , "labels" : [ { "id" : "12" , "name" : "Safety" } ], "submittedAt" : "2026-01-10T10:00:00.000Z" , "approvedAt" : "2026-01-12T10:00:00.000Z" , "deniedAt" : null , "attachments" : [ { "id" : "5011" , "type" : "file" , "label" : "Certificate scan" , "url" : "https://verify.example.org/abc" , "createdAt" : "2026-02-01T09:00:00.000Z" } ] }, "uploads" : [ { "attachmentId" : "5011" , "fileName" : "certificate.pdf" , "label" : "Certificate scan" , "uploadUrl" : " --- ## Flag a skill as a development focus URL: https://help.skillsdb.com/api-reference/person-skill/flag-a-skill-as-a-development-focus Flag a skill as a development focus cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "employee": true, "manager": true } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus" payload = { "employee": True, "manager": True } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({employee: true, manager: true}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'employee' => true, 'manager' => true ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus" payload := strings.NewReader("{\n \"employee\": true,\n \"manager\": true\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"employee\": true,\n \"manager\": true\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/focus") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"employee\": true,\n \"manager\": true\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skill --- ## Get a person's scorecard summary URL: https://help.skillsdb.com/api-reference/person-skill/get-a-persons-scorecard-summary Get a person's scorecard summary cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "careers" : [ { "assignmentId" : "9001" , "careerName" : "Warehouse Operator" , "levelId" : "7" , "levelName" : "Senior" , "totalSkills" : 18 } ], "totalIndividualSkills" : 6 , "averageGrade" : 2.8 , "highestGrade" : 4 , "totalUpskillingResources" : 12 , "totalUtilizedUpskillingResources" : 7 , "totalFocusedSkills" : 3 , "totalBenchmarkMet" : 15 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / scorecard Try it Get a person's scorecard summary cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/scorecard', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => --- ## Get one of a person's skills URL: https://help.skillsdb.com/api-reference/person-skill/get-one-of-a-persons-skills Get one of a person's skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } --- ## Get skill statistics for a person URL: https://help.skillsdb.com/api-reference/person-skill/get-skill-statistics-for-a-person Get skill statistics for a person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "attachedSkills" : 24 , "benchmarksMet" : 15 , "variances" : 6 , "skillGaps" : 9 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / skill-statistics Try it Get skill statistics for a person cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skill-statistics", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_T --- ## Grade a person across a career URL: https://help.skillsdb.com/api-reference/person-skill/grade-a-person-across-a-career Grade a person across a career cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "grades": [ { "skillId": "77", "managerGradeId": "3", "managerYearsOfExperience": 4, "selfGradeId": "2", "selfYearsOfExperience": 2 } ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades" payload = { "grades": [ { "skillId": "77", "managerGradeId": "3", "managerYearsOfExperience": 4, "selfGradeId": "2", "selfYearsOfExperience": 2 } ] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ grades: [ { skillId: '77', managerGradeId: '3', managerYearsOfExperience: 4, selfGradeId: '2', selfYearsOfExperience: 2 } ] }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'grades' => [ [ 'skillId' => '77', 'managerGradeId' => '3', 'managerYearsOfExperience' => 4, 'selfGradeId' => '2', 'selfYearsOfExperience' => 2 ] ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades" payload := strings.NewReader("{\n \"grades\": [\n {\n \"skillId\": \"77\",\n \"managerGradeId\": \"3\",\n \"managerYearsOfExperience\": 4,\n \"selfGradeId\": \"2\",\n \"selfYearsOfExperience\": 2\n }\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"grades\": [\n {\n \"skillId\": \"77\",\n \"managerGradeId\": \"3\",\n \"managerYearsOfExperience\": 4,\n \"selfGradeId\": \"2\",\n \"selfYearsOfExperience\": 2\n }\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/careers/{careerId}/grades") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"grades\": [\n {\n \"skillId\": \"77\",\n \"managerGradeId\": \"3\",\n \"managerYearsOfExperience\": 4,\n \"selfGradeId\": \"2\",\n \"selfYearsOfExperience\": 2\n }\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 422 429 500 { "data" : [ { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 --- ## Grade trends for a career URL: https://help.skillsdb.com/api-reference/person-skill/grade-trends-for-a-career Grade trends for a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "period" : "2026-03" , "averageManagerGrade" : 2.6 , "averageSelfGrade" : 2.4 , "recordCount" : 40 , "skill" : { "id" : "77" , "name" : "Forklift Operation" } } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / careers / {id} / grade-trends Try it Grade trends for a career cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/careers/{id}/grade-trends", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS --- ## List person skills for a population URL: https://help.skillsdb.com/api-reference/person-skill/list-person-skills-for-a-population List person skills for a population cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/person-skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/person-skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/person-skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/person-skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/person-skills" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/person-skills") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/person-skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "email" : "dana@example.com" , "manager" : { "id" : "1042" , "name" : "Dana Whitfield" }, "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "career" : { "id" : "77" , "name" : "Forklift Operation" }, "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "benchmark" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "notApplicable" : false , "selfGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedAt" : null , "lastTrainingDate" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / person-skills Try it List person skills for a population cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/person-skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/person-skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.c --- ## Mark a skill not applicable to a person URL: https://help.skillsdb.com/api-reference/person-skill/mark-a-skill-not-applicable-to-a-person Mark a skill not applicable to a person cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "notApplicable": true } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable" payload = { "notApplicable": True } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({notApplicable: true}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'notApplicable' => true ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable" payload := strings.NewReader("{\n \"notApplicable\": true\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"notApplicable\": true\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/not-applicable") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"notApplicable\": true\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": " --- ## Remove a skill from a person URL: https://help.skillsdb.com/api-reference/person-skill/remove-a-skill-from-a-person Remove a skill from a person cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / skills / {skillId} Try it Remove a skill from a person cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https:// --- ## Set a per-person benchmark on a skill URL: https://help.skillsdb.com/api-reference/person-skill/set-a-per-person-benchmark-on-a-skill Set a per-person benchmark on a skill cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "gradeId": "4" }' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark" payload = { "gradeId": "4" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({gradeId: '4'}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'gradeId' => '4' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark" payload := strings.NewReader("{\n \"gradeId\": \"4\"\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"gradeId\": \"4\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/benchmark") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"gradeId\": \"4\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", " --- ## Set a person's manager grade on a skill URL: https://help.skillsdb.com/api-reference/person-skill/set-a-persons-manager-grade-on-a-skill Set a person's manager grade on a skill cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "gradeId": "3", "yearsOfExperience": 4, "comment": "Completed the refresher in March." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade" payload = { "gradeId": "3", "yearsOfExperience": 4, "comment": "Completed the refresher in March." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ gradeId: '3', yearsOfExperience: 4, comment: 'Completed the refresher in March.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'gradeId' => '3', 'yearsOfExperience' => 4, 'comment' => 'Completed the refresher in March.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade" payload := strings.NewReader("{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/manager-grade") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "512", "name": "TIG Welding", "description": "Gas tungsten arc welding.", "isCertification": false, "selfGrade": { "id": "3", "grade": 3, "label": "Proficient" }, "selfYearsOfExperience": 4, "managerGrade": { "id": "3", "grade": 3, "label": "Proficient" }, "managerYearsOfExperience": 3, "managerGradeUpdatedAt": "2026-02-01T10:00:00.000Z", "managerGradeUpdatedBy": { "id": "1042", "name": "Dana Whitfield" }, "benchmark": { "effective": { "id": "3", "grade": 3, "label": "Proficient" }, "source": "manager", "manager": { "id": "3", "grade": 3, "label": "Proficient" }, "careers": [ { "careerId": "31", "careerName": "Warehouse Operator", "careerSkillId": "512", "levelId": "7", "levelName": "Senior", "career": { "id": "3", "grade": 3, "label": "Proficient" }, "level": { "id": "3", "grade": 3, "label": "Proficient" }, "effective": { "id": "3", "grade": 3, "label": "Proficient" }, "effectiveSource": "manager" } ] }, "notApplicable": false, "focus": { "employee": false, "manager": true }, "origin": { "direct": true, "careers": [ { "careerId": "31", "careerName": "Warehouse Operator", "careerSkillId": "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/set --- ## Set a person's self grade on a skill URL: https://help.skillsdb.com/api-reference/person-skill/set-a-persons-self-grade-on-a-skill Set a person's self grade on a skill cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "gradeId": "3", "yearsOfExperience": 4, "comment": "Completed the refresher in March." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade" payload = { "gradeId": "3", "yearsOfExperience": 4, "comment": "Completed the refresher in March." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ gradeId: '3', yearsOfExperience: 4, comment: 'Completed the refresher in March.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'gradeId' => '3', 'yearsOfExperience' => 4, 'comment' => 'Completed the refresher in March.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade" payload := strings.NewReader("{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/self-grade") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"gradeId\": \"3\",\n \"yearsOfExperience\": 4,\n \"comment\": \"Completed the refresher in March.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "u --- ## Skill matrix: people with a skill, and their grades URL: https://help.skillsdb.com/api-reference/person-skill/skill-matrix:-people-with-a-skill-and-their-grades Skill matrix: people with a skill, and their grades cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "email" : "dana@example.com" , "manager" : { "id" : "1042" , "name" : "Dana Whitfield" }, "skill" : { "id" : "77" , "name" : "Forklift Operation" }, "career" : { "id" : "77" , "name" : "Forklift Operation" }, "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "benchmark" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "notApplicable" : false , "selfGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedAt" : null , "lastTrainingDate" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / matrix Try it Skill matrix: people with a skill, and their grades cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/matrix" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: --- ## Approve a skill request URL: https://help.skillsdb.com/api-reference/skill-requests/approve-a-skill-request Approve a skill request cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "reason": "Covered by the existing Welding skill.", "notes": "Approved for the fabrication track." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve" payload = { "reason": "Covered by the existing Welding skill.", "notes": "Approved for the fabrication track." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ reason: 'Covered by the existing Welding skill.', notes: 'Approved for the fabrication track.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'reason' => 'Covered by the existing Welding skill.', 'notes' => 'Approved for the fabrication track.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve" payload := strings.NewReader("{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/approve") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "17" , "name" : "Welding" , "description" : "MIG and TIG welding." , "status" : "pending" , "requestedById" : "91" , "requestedAt" : "2026-03-01T09:00:00.000Z" , "reviewedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reviewNotes" : "Duplicate of Welding" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-d --- ## List skill requests URL: https://help.skillsdb.com/api-reference/skill-requests/list-skill-requests List skill requests cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-requests \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-requests" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-requests', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-requests", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-requests" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skill-requests") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-requests") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "17" , "name" : "Welding" , "description" : "MIG and TIG welding." , "status" : "pending" , "requestedById" : "91" , "requestedAt" : "2026-03-01T09:00:00.000Z" , "reviewedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reviewNotes" : "Duplicate of Welding" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skill-requests Try it List skill requests cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skill-requests \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-requests" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skill-requests', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-requests", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, C --- ## Reject a skill request URL: https://help.skillsdb.com/api-reference/skill-requests/reject-a-skill-request Reject a skill request cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "reason": "Covered by the existing Welding skill.", "notes": "Approved for the fabrication track." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject" payload = { "reason": "Covered by the existing Welding skill.", "notes": "Approved for the fabrication track." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ reason: 'Covered by the existing Welding skill.', notes: 'Approved for the fabrication track.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'reason' => 'Covered by the existing Welding skill.', 'notes' => 'Approved for the fabrication track.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject" payload := strings.NewReader("{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-requests/{id}/reject") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"reason\": \"Covered by the existing Welding skill.\",\n \"notes\": \"Approved for the fabrication track.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "17" , "name" : "Welding" , "description" : "MIG and TIG welding." , "status" : "pending" , "requestedById" : "91" , "requestedAt" : "2026-03-01T09:00:00.000Z" , "reviewedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reviewNotes" : "Duplicate of Welding" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/erro --- ## Request a skill URL: https://help.skillsdb.com/api-reference/skill-requests/request-a-skill Request a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skill-requests \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Welding", "description": "MIG and TIG welding." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skill-requests" payload = { "name": "Welding", "description": "MIG and TIG welding." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Welding', description: 'MIG and TIG welding.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/skill-requests', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skill-requests", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Welding', 'description' => 'MIG and TIG welding.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skill-requests" payload := strings.NewReader("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skill-requests") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skill-requests") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "17" , "name" : "Welding" , "description" : "MIG and TIG welding." , "status" : "pending" , "requestedById" : "91" , "requestedAt" : "2026-03-01T09:00:00.000Z" , "reviewedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reviewNotes" : "Duplicate of Welding" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/ --- ## Archive a skill URL: https://help.skillsdb.com/api-reference/skills/archive-a-skill Archive a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/archive \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/archive" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/archive', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/archive", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/archive" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skills/{id}/archive") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/archive") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "63" , "name" : "Welding" , "description" : "MIG and TIG welding." , "isCertification" : false , "isArchived" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / archive Try it Archive a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/archive \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/archive" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/archive', options) .then(res --- ## Assign skills to a person URL: https://help.skillsdb.com/api-reference/skills/assign-skills-to-a-person Assign skills to a person cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillIds": [ "512", "513" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" payload = { "skillIds": ["512", "513"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillIds: ['512', '513']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'skillIds' => [ '512', '513' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" payload := strings.NewReader("{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 2 , "skipped" : 1 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal t --- ## Create a skill URL: https://help.skillsdb.com/api-reference/skills/create-a-skill Create a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Welding", "description": "MIG and TIG welding." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills" payload = { "name": "Welding", "description": "MIG and TIG welding." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Welding', description: 'MIG and TIG welding.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Welding', 'description' => 'MIG and TIG welding.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills" payload := strings.NewReader("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "63" , "name" : "Welding" , "description" : "MIG and TIG welding." , "isCertification" : false , "isArchived" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/peop --- ## Delete a skill URL: https://help.skillsdb.com/api-reference/skills/delete-a-skill Delete a skill cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skills/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}" req, _ := http.NewRequest("DELETE", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/skills/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } DELETE https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} Try it Delete a skill cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/skills/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}" headers = {"Authorization": "Bearer "} response = requests.delete(url, headers=headers) print(response.text) const options = {method: 'DELETE', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/ --- ## Get a skill URL: https://help.skillsdb.com/api-reference/skills/get-a-skill Get a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "63" , "name" : "Welding" , "description" : "MIG and TIG welding." , "isCertification" : false , "isArchived" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} Try it Get a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else --- ## List a person's directly-assigned skills URL: https://help.skillsdb.com/api-reference/skills/list-a-persons-directly-assigned-skills List a person's directly-assigned skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "512" , "name" : "TIG Welding" , "description" : "Gas tungsten arc welding." , "isCertification" : false , "selfGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "selfYearsOfExperience" : 4 , "managerGrade" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "managerYearsOfExperience" : 3 , "managerGradeUpdatedAt" : "2026-02-01T10:00:00.000Z" , "managerGradeUpdatedBy" : { "id" : "1042" , "name" : "Dana Whitfield" }, "benchmark" : { "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "source" : "manager" , "manager" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" , "levelId" : "7" , "levelName" : "Senior" , "career" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "level" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effective" : { "id" : "3" , "grade" : 3 , "label" : "Proficient" }, "effectiveSource" : "manager" } ] }, "notApplicable" : false , "focus" : { "employee" : false , "manager" : true }, "origin" : { "direct" : true , "careers" : [ { "careerId" : "31" , "careerName" : "Warehouse Operator" , "careerSkillId" : "512" } ] } } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characte --- ## List a skill's activity URL: https://help.skillsdb.com/api-reference/skills/list-a-skills-activity List a skill's activity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/activity \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/activity", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/activity" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/activity") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/activity") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "event" : "version_created" , "description" : "Career renamed" , "performedById" : "88" , "performedAt" : "2026-03-02T14:00:00.000Z" , "versionId" : "402" , "affectedUserCount" : 4 , "renewalOption" : "with_approval" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / activity Try it List a skill's activity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/activity \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/activity", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => " --- ## List a skill's versions URL: https://help.skillsdb.com/api-reference/skills/list-a-skills-versions List a skill's versions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/versions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/versions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/versions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/versions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/versions" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/versions") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/versions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "402" , "name" : "Welding" , "description" : "MIG and TIG welding." , "editedById" : "88" , "editedAt" : "2026-03-02T14:00:00.000Z" , "changeNote" : "Clarified scope" , "isBaseline" : false } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / versions Try it List a skill's versions cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/versions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/versions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/versions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/versions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_ --- ## List people who hold a skill URL: https://help.skillsdb.com/api-reference/skills/list-people-who-hold-a-skill List people who hold a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "42" , "name" : "Welding" }, "email" : "jo@example.com" , "jobTitle" : "Fabricator" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / people Try it List people who hold a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/people \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ --- ## List skills URL: https://help.skillsdb.com/api-reference/skills/list-skills List skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "id": "63", "name": "Welding", "description": "MIG and TIG welding.", "isCertification": false, "isArchived": false, "usage": { "careers": [ { "id": "42", "name": "Welding" } ], "peopleCount": 12, "trainingDatesEnabled": true } } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills Try it List skills cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = cur --- ## Remove skills from a person URL: https://help.skillsdb.com/api-reference/skills/remove-skills-from-a-person Remove skills from a person cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "skillIds": [ "512", "513" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" payload = { "skillIds": ["512", "513"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({skillIds: ['512', '513']}) }; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'skillIds' => [ '512', '513' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills" payload := strings.NewReader("{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"skillIds\": [\n \"512\",\n \"513\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "affected" : 2 , "skipped" : 1 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter --- ## Unarchive a skill URL: https://help.skillsdb.com/api-reference/skills/unarchive-a-skill Unarchive a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "63" , "name" : "Welding" , "description" : "MIG and TIG welding." , "isCertification" : false , "isArchived" : false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / unarchive Try it Unarchive a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/unarchive& --- ## Update a skill URL: https://help.skillsdb.com/api-reference/skills/update-a-skill Update a skill cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/skills/{id} \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data ' { "name": "Welding", "description": "MIG and TIG welding." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}" payload = { "name": "Welding", "description": "MIG and TIG welding." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({name: 'Welding', description: 'MIG and TIG welding.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Welding', 'description' => 'MIG and TIG welding.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}" payload := strings.NewReader("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/skills/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Welding\",\n \"description\": \"MIG and TIG welding.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "63", "name": "Welding", "description": "MIG and TIG welding.", "isCertification": false, "isArchived": false } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "li --- ## Cancel a survey URL: https://help.skillsdb.com/api-reference/survey/cancel-a-survey Cancel a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data": { "id": "301", "name": "Q3 onboarding pulse", "description": null, "status": "launched", "templateVersion": { "id": "88", "name": "Onboarding pulse", "version": "2.1", "templateId": "12", "templateName": "Onboarding pulse" }, "toAllPeople": true, "scheduledFor": null, "launchedAt": "2026-07-01T08:00:00.000Z", "dueDate": "2026-07-31T00:00:00.000Z", "lastNudgeSentAt": null, "participants": { "notStarted": 40, "inProgress": 12, "completed": 25 }, "createdById": "1042", "createdAt": "2026-06-20T09:00:00.000Z", "updatedAt": null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / cancel Try it Cancel a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/cancel \ --header 'Authorizatio --- ## Create a survey URL: https://help.skillsdb.com/api-reference/survey/create-a-survey Create a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Q3 onboarding pulse", "templateVersionId": "88", "toAllPeople": false, "businessUnitIds": [ "<string>" ], "divisionIds": [ "<string>" ], "countryIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "departmentIds": [ "<string>" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ], "people": [ "<string>" ], "description": "Sent to everyone who joined this quarter.", "dueDate": "2026-07-31T00:00:00.000Z", "scheduledFor": "2026-07-01T08:00:00.000Z" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys" payload = { "name": "Q3 onboarding pulse", "templateVersionId": "88", "toAllPeople": False, "businessUnitIds": [""], "divisionIds": [""], "countryIds": [""], "businessRegionIds": [""], "cityIds": [""], "siteIds": [""], "departmentIds": [""], "teamIds": [""], "shiftIds": [""], "people": [""], "description": "Sent to everyone who joined this quarter.", "dueDate": "2026-07-31T00:00:00.000Z", "scheduledFor": "2026-07-01T08:00:00.000Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Q3 onboarding pulse', templateVersionId: '88', toAllPeople: false, businessUnitIds: [''], divisionIds: [''], countryIds: [''], businessRegionIds: [''], cityIds: [''], siteIds: [''], departmentIds: [''], teamIds: [''], shiftIds: [''], people: [''], description: 'Sent to everyone who joined this quarter.', dueDate: '2026-07-31T00:00:00.000Z', scheduledFor: '2026-07-01T08:00:00.000Z' }) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Q3 onboarding pulse', 'templateVersionId' => '88', 'toAllPeople' => false, 'businessUnitIds' => [ '' ], 'divisionIds' => [ '' ], 'countryIds' => [ '' ], 'businessRegionIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'departmentIds' => [ '' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ], 'people' => [ '' ], 'description' => 'Sent to everyone who joined this quarter.', 'dueDate' => '2026-07-31T00:00:00.000Z', 'scheduledFor' => '2026-07-01T08:00:00.000Z' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys" payload := strings.NewReader("{\n \"name\": \"Q3 onboarding pulse\",\n \"templateVersionId\": \"88\",\n \"toAllPeople\": false,\n \"businessUnitIds\": [\n \"\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ],\n \"people\": [\n \"\"\n ],\n \"description\": \"Sent to everyone who joined this quarter.\",\n \"dueDate\": \"2026-07-31T00:00:00.000Z\",\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Q3 onboarding pulse\",\n \"templateVersionId\": \"88\",\n \"toAllPeople\": false,\n \"businessUnitIds\": [\n \"\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ],\n \"people\": [\n \"\"\n ],\n \"description\": \"Sent to everyone who joined this quarter.\",\n \"dueDate\": \"2026-07-31T00:00:00.000Z\",\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/survey --- ## End a survey URL: https://help.skillsdb.com/api-reference/survey/end-a-survey End a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/end \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/end" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/end', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/end", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/end" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/end") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/end") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / end Try it End a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/end \ --header 'Authorization: --- ## Exclude people from a survey URL: https://help.skillsdb.com/api-reference/survey/exclude-people-from-a-survey Exclude people from a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "people": [ "dana@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions" payload = { "people": ["dana@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({people: ['dana@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'people' => [ 'dana@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions" payload := strings.NewReader("{\n \"people\": [\n \"dana@example.com\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"people\": [\n \"dana@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"people\": [\n \"dana@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "toAllPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [ "<string>" ], "countryIds" : [ "<string>" ], "businessRegionIds" : [ "<string>" ], "cityIds" : [ "<string>" ], "siteIds" : [ "<string>" ], "departmentIds" : [ "<string>" ], "teamIds" : [ "<string>" ], "shiftIds" : [ "<string>" ], "stateIds" : [ "<string>" ], "personIds" : [ "<string>" ], "excludedPersonIds" : [ "<string>" ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expire --- ## Get a download link for an uploaded response URL: https://help.skillsdb.com/api-reference/survey/get-a-download-link-for-an-uploaded-response Get a download link for an uploaded response cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "url" : "<string>" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / responses / {responseId} / download-url Try it Get a download link for an uploaded response cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses/{responseId}/download-url', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surv --- ## Get a person's participation URL: https://help.skillsdb.com/api-reference/survey/get-a-persons-participation Get a person's participation cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "person" : { "id" : "1042" , "name" : "Dana Whitfield" }, "status" : "assigned" , "includedVia" : "all_people" , "startedAt" : null , "completedAt" : null , "includedAt" : "2026-07-01T08:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / people / {personId} Try it Get a person's participation cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}", CURLOPT_RETURNTRAN --- ## Get a survey URL: https://help.skillsdb.com/api-reference/survey/get-a-survey Get a survey cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} Try it Get a survey cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "toAllPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [ "<string>" ], "countryIds" : [ "<string>" ], "businessRegionIds" : [ "<string>" ], "cityIds" : [ "<string>" ], "siteIds" : [ "<string>" ], "departmentIds" : [ "<string>" ], "teamIds" : [ "<string>" ], "shiftIds" : [ "<string>" ], "stateIds" : [ "<string>" ], "personIds" : [ "<string>" ], "excludedPersonIds" : [ "<string>" ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / scope Try it Get a survey's population definition cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "7001" , "questionVersionId" : "410" , "questionTemplateId" : "41" , "name" : "Manager support" , "text" : "My manager supports my development." , "description" : null , "version" : "1.0" , "type" : "rating" , "responseRequired" : true , "allowsMultipleResponses" : false , "position" : 1 , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "description" : null , "position" : 1 } ] } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / questions Try it Get a survey's question set cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/questions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => consol --- ## Launch a survey URL: https://help.skillsdb.com/api-reference/survey/launch-a-survey Launch a survey cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "dueDate": "2026-07-31T00:00:00.000Z" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch" payload = { "dueDate": "2026-07-31T00:00:00.000Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({dueDate: '2026-07-31T00:00:00.000Z'}) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'dueDate' => '2026-07-31T00:00:00.000Z' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch" payload := strings.NewReader("{\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/launch") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_l --- ## Lift exclusions from a survey URL: https://help.skillsdb.com/api-reference/survey/lift-exclusions-from-a-survey Lift exclusions from a survey cURL curl --request DELETE \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "people": [ "dana@example.com" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions" payload = { "people": ["dana@example.com"] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.delete(url, json=payload, headers=headers) print(response.text) const options = { method: 'DELETE', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({people: ['dana@example.com']}) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "DELETE", CURLOPT_POSTFIELDS => json_encode([ 'people' => [ 'dana@example.com' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions" payload := strings.NewReader("{\n \"people\": [\n \"dana@example.com\"\n ]\n}") req, _ := http.NewRequest("DELETE", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.delete("https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"people\": [\n \"dana@example.com\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/exclusions") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Delete.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"people\": [\n \"dana@example.com\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "toAllPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [ "<string>" ], "countryIds" : [ "<string>" ], "businessRegionIds" : [ "<string>" ], "cityIds" : [ "<string>" ], "siteIds" : [ "<string>" ], "departmentIds" : [ "<string>" ], "teamIds" : [ "<string>" ], "shiftIds" : [ "<string>" ], "stateIds" : [ "<string>" ], "personIds" : [ "<string>" ], "excludedPersonIds" : [ "<string>" ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error" --- ## List a person's responses URL: https://help.skillsdb.com/api-reference/survey/list-a-persons-responses List a person's responses cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "9001" , "personId" : "1042" , "question" : { "id" : "7001" , "questionVersionId" : "410" , "name" : "Manager support" , "text" : "My manager supports my development." , "version" : "1.0" , "type" : "multiple_choice" , "position" : 1 }, "answer" : { "kind" : "text" , "text" : "More pairing time with senior riggers." , "rating" : null , "fileName" : null , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "conditionalValue" : null } ], "certificationCount" : 0 }, "createdAt" : "2026-07-02T10:00:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / people / {personId} / responses Try it List a person's responses cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses" headers = {"Authorization": "Bearer "} re --- ## List a survey's responses URL: https://help.skillsdb.com/api-reference/survey/list-a-surveys-responses List a survey's responses cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "9001" , "personId" : "1042" , "question" : { "id" : "7001" , "questionVersionId" : "410" , "name" : "Manager support" , "text" : "My manager supports my development." , "version" : "1.0" , "type" : "multiple_choice" , "position" : 1 }, "answer" : { "kind" : "text" , "text" : "More pairing time with senior riggers." , "rating" : null , "fileName" : null , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "conditionalValue" : null } ], "certificationCount" : 0 }, "createdAt" : "2026-07-02T10:00:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / responses Try it List a survey's responses cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/responses" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://pr --- ## List people in a survey URL: https://help.skillsdb.com/api-reference/survey/list-people-in-a-survey List people in a survey cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "person": { "id": "1042", "name": "Dana Whitfield" }, "status": "assigned", "includedVia": "all_people", "startedAt": null, "completedAt": null, "includedAt": "2026-07-01T08:00:00.000Z" } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / people Try it List people in a survey cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VE --- ## List surveys URL: https://help.skillsdb.com/api-reference/survey/list-surveys List surveys cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/surveys") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys Try it List surveys cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/surveys \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 400 401 403 404 409 429 500 { "type" : "https://help.skillsdb.com/api-docs/errors/validation-error" , "title" : "Validation failed" , "status" : 400 , "detail" : "limit must be between 1 and 200" , "instance" : "/api/v1/people" , "requestId" : "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e" , "errors" : [ { "field" : "email" , "code" : "max_length" , "message" : "email must be shorter than or equal to 75 characters" } ], "error" : "trial_expired" , "upgrade_url" : "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / surveys / {id} / nudge Try it Nudge participants cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/nudge', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' \ --header 'Content-Type: application/json' \ --data ' { "scheduledFor": "2026-07-01T08:00:00.000Z", "dueDate": "2026-07-31T00:00:00.000Z" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule" payload = { "scheduledFor": "2026-07-01T08:00:00.000Z", "dueDate": "2026-07-31T00:00:00.000Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({scheduledFor: '2026-07-01T08:00:00.000Z', dueDate: '2026-07-31T00:00:00.000Z'}) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'scheduledFor' => '2026-07-01T08:00:00.000Z', 'dueDate' => '2026-07-31T00:00:00.000Z' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule" payload := strings.NewReader("{\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/schedule") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"dueDate\": \"2026-07-31T00:00:00.000Z\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error --- ## Scope a survey to a population URL: https://help.skillsdb.com/api-reference/survey/scope-a-survey-to-a-population Scope a survey to a population cURL curl --request PUT \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "toAllPeople": false, "businessUnitIds": [ "<string>" ], "divisionIds": [ "<string>" ], "countryIds": [ "<string>" ], "businessRegionIds": [ "<string>" ], "cityIds": [ "<string>" ], "siteIds": [ "<string>" ], "departmentIds": [ "<string>" ], "teamIds": [ "<string>" ], "shiftIds": [ "<string>" ], "people": [ "<string>" ] } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope" payload = { "toAllPeople": False, "businessUnitIds": [""], "divisionIds": [""], "countryIds": [""], "businessRegionIds": [""], "cityIds": [""], "siteIds": [""], "departmentIds": [""], "teamIds": [""], "shiftIds": [""], "people": [""] } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.put(url, json=payload, headers=headers) print(response.text) const options = { method: 'PUT', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ toAllPeople: false, businessUnitIds: [''], divisionIds: [''], countryIds: [''], businessRegionIds: [''], cityIds: [''], siteIds: [''], departmentIds: [''], teamIds: [''], shiftIds: [''], people: [''] }) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PUT", CURLOPT_POSTFIELDS => json_encode([ 'toAllPeople' => false, 'businessUnitIds' => [ '' ], 'divisionIds' => [ '' ], 'countryIds' => [ '' ], 'businessRegionIds' => [ '' ], 'cityIds' => [ '' ], 'siteIds' => [ '' ], 'departmentIds' => [ '' ], 'teamIds' => [ '' ], 'shiftIds' => [ '' ], 'people' => [ '' ] ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope" payload := strings.NewReader("{\n \"toAllPeople\": false,\n \"businessUnitIds\": [\n \"\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ],\n \"people\": [\n \"\"\n ]\n}") req, _ := http.NewRequest("PUT", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.put("https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"toAllPeople\": false,\n \"businessUnitIds\": [\n \"\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ],\n \"people\": [\n \"\"\n ]\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/scope") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Put.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"toAllPeople\": false,\n \"businessUnitIds\": [\n \"\"\n ],\n \"divisionIds\": [\n \"\"\n ],\n \"countryIds\": [\n \"\"\n ],\n \"businessRegionIds\": [\n \"\"\n ],\n \"cityIds\": [\n \"\"\n ],\n \"siteIds\": [\n \"\"\n ],\n \"departmentIds\": [\n \"\"\n ],\n \"teamIds\": [\n \"\"\n ],\n \"shiftIds\": [\n \"\"\n ],\n \"people\": [\n \"\"\n ]\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "toAllPeople" : false , "businessUnitIds" : [ "3" ], "divisionIds" : [ "<string>" ], "countryIds" : [ "<string>" ], "businessRegionIds" : [ "<string>" ], "cityIds" : [ "<string>" ], "siteIds" : [ "<string>" ], "departmentIds" : [ "<string>" ], "teamIds" : [ "<string>" ], "shiftIds" : [ "<string>" ], "stateIds" : [ "<string>" ], "personIds" : [ "<string>" ], "excludedPersonIds" : [ "<string>" ] } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, --- ## Submit a response URL: https://help.skillsdb.com/api-reference/survey/submit-a-response Submit a response cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "questionId": "7001", "text": "More pairing time with senior riggers.", "rating": 4, "optionIds": [ "<string>" ], "conditionalAnswers": [ { "optionId": "5003", "value": "Other: night shift" } ], "fileName": "evidence.pdf" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses" payload = { "questionId": "7001", "text": "More pairing time with senior riggers.", "rating": 4, "optionIds": [""], "conditionalAnswers": [ { "optionId": "5003", "value": "Other: night shift" } ], "fileName": "evidence.pdf" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ questionId: '7001', text: 'More pairing time with senior riggers.', rating: 4, optionIds: [''], conditionalAnswers: [{optionId: '5003', value: 'Other: night shift'}], fileName: 'evidence.pdf' }) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'questionId' => '7001', 'text' => 'More pairing time with senior riggers.', 'rating' => 4, 'optionIds' => [ '' ], 'conditionalAnswers' => [ [ 'optionId' => '5003', 'value' => 'Other: night shift' ] ], 'fileName' => 'evidence.pdf' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses" payload := strings.NewReader("{\n \"questionId\": \"7001\",\n \"text\": \"More pairing time with senior riggers.\",\n \"rating\": 4,\n \"optionIds\": [\n \"\"\n ],\n \"conditionalAnswers\": [\n {\n \"optionId\": \"5003\",\n \"value\": \"Other: night shift\"\n }\n ],\n \"fileName\": \"evidence.pdf\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"questionId\": \"7001\",\n \"text\": \"More pairing time with senior riggers.\",\n \"rating\": 4,\n \"optionIds\": [\n \"\"\n ],\n \"conditionalAnswers\": [\n {\n \"optionId\": \"5003\",\n \"value\": \"Other: night shift\"\n }\n ],\n \"fileName\": \"evidence.pdf\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}/people/{personId}/responses") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"questionId\": \"7001\",\n \"text\": \"More pairing time with senior riggers.\",\n \"rating\": 4,\n \"optionIds\": [\n \"\"\n ],\n \"conditionalAnswers\": [\n {\n \"optionId\": \"5003\",\n \"value\": \"Other: night shift\"\n }\n ],\n \"fileName\": \"evidence.pdf\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "response" : { "id" : "9001" , "personId" : "1042" , "question" : { "id" : "7001" , "questionVersionId" : "410" , "name" : "Manager support" , "text" : "My manager supports my development." , "version" : "1.0" , "type" : "multiple_choice" , "position" : 1 }, "answer" : { "kind" : "text" , "text" : "More pairing time with senior riggers." , "rating" : null , "fileName" : null , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "conditionalValue" : null } ], "certificationCount" : 0 }, "createdAt" : "2026-07-02T10:00:00.000Z" , "updatedAt" : null }, "uploadUrl" : "<string>" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or --- ## Update a survey URL: https://help.skillsdb.com/api-reference/survey/update-a-survey Update a survey cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/surveys/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Q3 onboarding pulse (revised)", "description": "<string>", "dueDate": "2026-08-15T00:00:00.000Z", "scheduledFor": "2026-07-01T08:00:00.000Z", "templateVersionId": "89" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/surveys/{id}" payload = { "name": "Q3 onboarding pulse (revised)", "description": "", "dueDate": "2026-08-15T00:00:00.000Z", "scheduledFor": "2026-07-01T08:00:00.000Z", "templateVersionId": "89" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Q3 onboarding pulse (revised)', description: '', dueDate: '2026-08-15T00:00:00.000Z', scheduledFor: '2026-07-01T08:00:00.000Z', templateVersionId: '89' }) }; fetch('https://prod.skillsdbnext.com/api/v1/surveys/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/surveys/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Q3 onboarding pulse (revised)', 'description' => '', 'dueDate' => '2026-08-15T00:00:00.000Z', 'scheduledFor' => '2026-07-01T08:00:00.000Z', 'templateVersionId' => '89' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/surveys/{id}" payload := strings.NewReader("{\n \"name\": \"Q3 onboarding pulse (revised)\",\n \"description\": \"\",\n \"dueDate\": \"2026-08-15T00:00:00.000Z\",\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"templateVersionId\": \"89\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/surveys/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Q3 onboarding pulse (revised)\",\n \"description\": \"\",\n \"dueDate\": \"2026-08-15T00:00:00.000Z\",\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"templateVersionId\": \"89\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/surveys/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Q3 onboarding pulse (revised)\",\n \"description\": \"\",\n \"dueDate\": \"2026-08-15T00:00:00.000Z\",\n \"scheduledFor\": \"2026-07-01T08:00:00.000Z\",\n \"templateVersionId\": \"89\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "301" , "name" : "Q3 onboarding pulse" , "description" : null , "status" : "launched" , "templateVersion" : { "id" : "88" , "name" : "Onboarding pulse" , "version" : "2.1" , "templateId" : "12" , "templateName" : "Onboarding pulse" }, "toAllPeople" : true , "scheduledFor" : null , "launchedAt" : "2026-07-01T08:00:00.000Z" , "dueDate" : "2026-07-31T00:00:00.000Z" , "lastNudgeSentAt" : null , "participants" : { "notStarted" : 40 , "inProgress" : 12 , "completed" : 25 }, "createdById" : "1042" , "createdAt" : "2026-06-20T09:00:00.000Z" , "updatedAt" : null } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "ti --- ## Create a survey template URL: https://help.skillsdb.com/api-reference/surveys/create-a-survey-template Create a survey template cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/survey-templates \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "name": "Quarterly engagement", "questions": [ { "name": "Manager support", "text": "My manager supports my development.", "type": "rating", "responseRequired": true, "allowsMultipleResponses": false, "options": [ { "label": "Strongly agree" } ] } ], "description": "Runs every quarter.", "visibility": "visible_to_all" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/survey-templates" payload = { "name": "Quarterly engagement", "questions": [ { "name": "Manager support", "text": "My manager supports my development.", "type": "rating", "responseRequired": True, "allowsMultipleResponses": False, "options": [{ "label": "Strongly agree" }] } ], "description": "Runs every quarter.", "visibility": "visible_to_all" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ name: 'Quarterly engagement', questions: [ { name: 'Manager support', text: 'My manager supports my development.', type: 'rating', responseRequired: true, allowsMultipleResponses: false, options: [{label: 'Strongly agree'}] } ], description: 'Runs every quarter.', visibility: 'visible_to_all' }) }; fetch('https://prod.skillsdbnext.com/api/v1/survey-templates', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/survey-templates", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'name' => 'Quarterly engagement', 'questions' => [ [ 'name' => 'Manager support', 'text' => 'My manager supports my development.', 'type' => 'rating', 'responseRequired' => true, 'allowsMultipleResponses' => false, 'options' => [ [ 'label' => 'Strongly agree' ] ] ] ], 'description' => 'Runs every quarter.', 'visibility' => 'visible_to_all' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/survey-templates" payload := strings.NewReader("{\n \"name\": \"Quarterly engagement\",\n \"questions\": [\n {\n \"name\": \"Manager support\",\n \"text\": \"My manager supports my development.\",\n \"type\": \"rating\",\n \"responseRequired\": true,\n \"allowsMultipleResponses\": false,\n \"options\": [\n {\n \"label\": \"Strongly agree\"\n }\n ]\n }\n ],\n \"description\": \"Runs every quarter.\",\n \"visibility\": \"visible_to_all\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/survey-templates") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"name\": \"Quarterly engagement\",\n \"questions\": [\n {\n \"name\": \"Manager support\",\n \"text\": \"My manager supports my development.\",\n \"type\": \"rating\",\n \"responseRequired\": true,\n \"allowsMultipleResponses\": false,\n \"options\": [\n {\n \"label\": \"Strongly agree\"\n }\n ]\n }\n ],\n \"description\": \"Runs every quarter.\",\n \"visibility\": \"visible_to_all\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/survey-templates") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"Quarterly engagement\",\n \"questions\": [\n {\n \"name\": \"Manager support\",\n \"text\": \"My manager supports my development.\",\n \"type\": \"rating\",\n \"responseRequired\": true,\n \"allowsMultipleResponses\": false,\n \"options\": [\n {\n \"label\": \"Strongly agree\"\n }\n ]\n }\n ],\n \"description\": \"Runs every quarter.\",\n \"visibility\": \"visible_to_all\"\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "58" , "name" : "Quarterly engagement" , "description" : "Runs every quarter." , "visibility" : "visible_to_all" , "isActive" : true , "latestVersion" : { "id" : "412" , "version" : "1.1" , "createdAt" : "2026-09-18T09:30:00.000Z" }, "versionCount" : 2 , "questions" : [ { "id" : "7001" , "questionVersionId" : "410" , "questionTemplateId" : "41" , "name" : "Manager support" , "text" : "My manager supports my development." , "description" : null , "version" : "1.0" , "type" : "rating" , "responseRequired" : true , "allowsMultipleResponses" : false , "position" : 1 , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "description" : null , "position" : 1 } ] } ], "createdAt" : "2026-09-18T09:30:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/ --- ## Get a survey template URL: https://help.skillsdb.com/api-reference/surveys/get-a-survey-template Get a survey template cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/survey-templates/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/survey-templates/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/survey-templates/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/survey-templates/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/survey-templates/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/survey-templates/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/survey-templates/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "58" , "name" : "Quarterly engagement" , "description" : "Runs every quarter." , "visibility" : "visible_to_all" , "isActive" : true , "latestVersion" : { "id" : "412" , "version" : "1.1" , "createdAt" : "2026-09-18T09:30:00.000Z" }, "versionCount" : 2 , "questions" : [ { "id" : "7001" , "questionVersionId" : "410" , "questionTemplateId" : "41" , "name" : "Manager support" , "text" : "My manager supports my development." , "description" : null , "version" : "1.0" , "type" : "rating" , "responseRequired" : true , "allowsMultipleResponses" : false , "position" : 1 , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "description" : null , "position" : 1 } ] } ], "createdAt" : "2026-09-18T09:30:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / survey-templates / {id} Try it Get a survey template cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/survey-templates/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/survey-templates/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'G --- ## List survey templates URL: https://help.skillsdb.com/api-reference/surveys/list-survey-templates List survey templates cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/survey-templates \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/survey-templates" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/survey-templates', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/survey-templates", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/survey-templates" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/survey-templates") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/survey-templates") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "58" , "name" : "Quarterly engagement" , "description" : "Runs every quarter." , "visibility" : "visible_to_all" , "isActive" : true , "latestVersion" : { "id" : "412" , "version" : "1.1" , "createdAt" : "2026-09-18T09:30:00.000Z" }, "versionCount" : 2 , "questions" : [ { "id" : "7001" , "questionVersionId" : "410" , "questionTemplateId" : "41" , "name" : "Manager support" , "text" : "My manager supports my development." , "description" : null , "version" : "1.0" , "type" : "rating" , "responseRequired" : true , "allowsMultipleResponses" : false , "position" : 1 , "options" : [ { "id" : "5001" , "label" : "Strongly agree" , "description" : null , "position" : 1 } ] } ], "createdAt" : "2026-09-18T09:30:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / survey-templates Try it List survey templates cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/survey-templates \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/survey-templates" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {meth --- ## Approve a training URL: https://help.skillsdb.com/api-reference/training/approve-a-training Approve a training cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve" headers = {"Authorization": "Bearer "} response = requests.post(url, headers=headers) print(response.text) const options = {method: 'POST', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve" req, _ := http.NewRequest("POST", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}/approve") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } POST https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api --- ## Cancel a training URL: https://help.skillsdb.com/api-reference/training/cancel-a-training Cancel a training cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "reason": "Practical assessment not evidenced." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel" payload = { "reason": "Practical assessment not evidenced." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({reason: 'Practical assessment not evidenced.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'reason' => 'Practical assessment not evidenced.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel" payload := strings.NewReader("{\n \"reason\": \"Practical assessment not evidenced.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"reason\": \"Practical assessment not evidenced.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}/cancel") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"reason\": \"Practical assessment not evidenced.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validati --- ## Get a training record URL: https://help.skillsdb.com/api-reference/training/get-a-training-record Get a training record cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/trainings/{id}") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / trainings / {id} Try it Get a training record cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id} \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/t --- ## Get download links for training evidence URL: https://help.skillsdb.com/api-reference/training/get-download-links-for-training-evidence Get download links for training evidence cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "17" , "fileName" : "certificate.pdf" , "url" : "https://storage.example.com/..." } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / trainings / {id} / evidence Try it Get download links for training evidence cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/evidence", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP --- ## List a person's approval activity URL: https://help.skillsdb.com/api-reference/training/list-a-persons-approval-activity List a person's approval activity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data": [ { "trainingId": "5120", "outcome": "rejected", "decidedAt": "2026-03-02T14:00:00.000Z", "reason": null, "person": { "id": "42", "name": "Welding" }, "skill": { "id": "42", "name": "Welding" }, "isSuperseded": false } ], "meta": { "total": 1342, "limit": 50, "offset": 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / approval-activity Try it List a person's approval activity cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity \ --header 'Authorization: Bearer ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-activity', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); ' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / approval-requests Try it List a person's approval requests cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/approval-requests \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext --- ## List a person's learning plans URL: https://help.skillsdb.com/api-reference/training/list-a-persons-learning-plans List a person's learning plans cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "310" , "personId" : "91" , "learning" : { "id" : "42" , "name" : "Welding" }, "state" : "in_progress" , "dueDate" : "2026-04-01T00:00:00.000Z" , "isPastDue" : false , "dueDateSetById" : "88" , "rating" : "positive" , "careerAssignmentId" : "42" , "assignedAt" : "2026-01-12T08:30:00.000Z" , "startedAt" : null , "completedAt" : null } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / learning-plans Try it List a person's learning plans cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/learning-plans', options) .then(res => res.jso --- ## List a person's training log for a skill URL: https://help.skillsdb.com/api-reference/training/list-a-persons-training-log-for-a-skill List a person's training log for a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/people/{personId}/skills/{skillId}/training-log") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / people / {personId} / skills / {skillId} / training-log Try it List a person's training log for a skill cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/people/{personId}/ --- ## List potential approvers URL: https://help.skillsdb.com/api-reference/training/list-potential-approvers List potential approvers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "person" : { "id" : "42" , "name" : "Welding" }, "email" : "dana@example.com" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / trainings / {id} / potential-approvers Try it List potential approvers cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/potential-approvers", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING --- ## List training approvals URL: https://help.skillsdb.com/api-reference/training/list-training-approvals List training approvals cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/training-approvals \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/training-approvals" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/training-approvals', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/training-approvals", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/training-approvals" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/training-approvals") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/training-approvals") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / training-approvals Try it List training approvals cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/training-approvals \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/training-approvals" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', --- ## List training records URL: https://help.skillsdb.com/api-reference/training/list-training-records List training records cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/trainings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/trainings") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : [ { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } ], "meta" : { "total" : 1342 , "limit" : 50 , "offset" : 0 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / trainings Try it List training records cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/trainings \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.c --- ## Preview a training renewal URL: https://help.skillsdb.com/api-reference/training/preview-a-training-renewal Preview a training renewal cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => [ "Authorization: Bearer " ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "Bearer ") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.get("https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview") .header("Authorization", "Bearer ") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = 'Bearer ' response = http.request(request) puts response.read_body 200 400 401 403 404 429 500 { "data" : { "withApproval" : 12 , "awaitingApproval" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } GET https://prod.skillsdbnext.com https://staging.skillsdbnext.com / api / v1 / skills / {id} / renew-training / preview Try it Preview a training renewal cURL curl --request GET \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview \ --header 'Authorization: Bearer <token>' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview" headers = {"Authorization": "Bearer "} response = requests.get(url, headers=headers) print(response.text) const options = {method: 'GET', headers: {Authorization: 'Bearer '}}; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training/preview", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_ --- ## Record a training URL: https://help.skillsdb.com/api-reference/training/record-a-training Record a training cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/trainings \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "email": "ada@example.com", "skillId": "63", "trainingDate": "2026-02-10T00:00:00.000Z", "trainer": "J. Instructor", "evidenceNote": "Completed the practical assessment.", "delegatedApproverEmail": "dana@example.com", "preApproved": false, "notApplicable": false } ' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings" payload = { "email": "ada@example.com", "skillId": "63", "trainingDate": "2026-02-10T00:00:00.000Z", "trainer": "J. Instructor", "evidenceNote": "Completed the practical assessment.", "delegatedApproverEmail": "dana@example.com", "preApproved": False, "notApplicable": False } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ email: 'ada@example.com', skillId: '63', trainingDate: '2026-02-10T00:00:00.000Z', trainer: 'J. Instructor', evidenceNote: 'Completed the practical assessment.', delegatedApproverEmail: 'dana@example.com', preApproved: false, notApplicable: false }) }; fetch('https://prod.skillsdbnext.com/api/v1/trainings', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'email' => 'ada@example.com', 'skillId' => '63', 'trainingDate' => '2026-02-10T00:00:00.000Z', 'trainer' => 'J. Instructor', 'evidenceNote' => 'Completed the practical assessment.', 'delegatedApproverEmail' => 'dana@example.com', 'preApproved' => false, 'notApplicable' => false ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings" payload := strings.NewReader("{\n \"email\": \"ada@example.com\",\n \"skillId\": \"63\",\n \"trainingDate\": \"2026-02-10T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Completed the practical assessment.\",\n \"delegatedApproverEmail\": \"dana@example.com\",\n \"preApproved\": false,\n \"notApplicable\": false\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/trainings") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"email\": \"ada@example.com\",\n \"skillId\": \"63\",\n \"trainingDate\": \"2026-02-10T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Completed the practical assessment.\",\n \"delegatedApproverEmail\": \"dana@example.com\",\n \"preApproved\": false,\n \"notApplicable\": false\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"email\": \"ada@example.com\",\n \"skillId\": \"63\",\n \"trainingDate\": \"2026-02-10T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Completed the practical assessment.\",\n \"delegatedApproverEmail\": \"dana@example.com\",\n \"preApproved\": false,\n \"notApplicable\": false\n}" response = http.request(request) puts response.read_body 201 400 401 403 404 409 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c --- ## Reject a training URL: https://help.skillsdb.com/api-reference/training/reject-a-training Reject a training cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "reason": "Practical assessment not evidenced." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject" payload = { "reason": "Practical assessment not evidenced." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({reason: 'Practical assessment not evidenced.'}) }; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'reason' => 'Practical assessment not evidenced.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject" payload := strings.NewReader("{\n \"reason\": \"Practical assessment not evidenced.\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"reason\": \"Practical assessment not evidenced.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}/reject") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"reason\": \"Practical assessment not evidenced.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validati --- ## Renew training on a skill URL: https://help.skillsdb.com/api-reference/training/renew-training-on-a-skill Renew training on a skill cURL curl --request POST \ --url https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "option": "with_approval" } ' import requests url = "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training" payload = { "option": "with_approval" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.text) const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({option: 'with_approval'}) }; fetch('https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => json_encode([ 'option' => 'with_approval' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training" payload := strings.NewReader("{\n \"option\": \"with_approval\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.post("https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"option\": \"with_approval\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/skills/{id}/renew-training") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"option\": \"with_approval\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "withApproval" : 12 , "awaitingApproval" : 3 } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "t --- ## Update a training URL: https://help.skillsdb.com/api-reference/training/update-a-training Update a training cURL curl --request PATCH \ --url https://prod.skillsdbnext.com/api/v1/trainings/{id} \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data ' { "trainingDate": "2026-02-11T00:00:00.000Z", "trainer": "J. Instructor", "evidenceNote": "Amended evidence note." } ' import requests url = "https://prod.skillsdbnext.com/api/v1/trainings/{id}" payload = { "trainingDate": "2026-02-11T00:00:00.000Z", "trainer": "J. Instructor", "evidenceNote": "Amended evidence note." } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.patch(url, json=payload, headers=headers) print(response.text) const options = { method: 'PATCH', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: JSON.stringify({ trainingDate: '2026-02-11T00:00:00.000Z', trainer: 'J. Instructor', evidenceNote: 'Amended evidence note.' }) }; fetch('https://prod.skillsdbnext.com/api/v1/trainings/{id}', options) .then(res => res.json()) .then(res => console.log(res)) .catch(err => console.error(err)); "https://prod.skillsdbnext.com/api/v1/trainings/{id}", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "PATCH", CURLOPT_POSTFIELDS => json_encode([ 'trainingDate' => '2026-02-11T00:00:00.000Z', 'trainer' => 'J. Instructor', 'evidenceNote' => 'Amended evidence note.' ]), CURLOPT_HTTPHEADER => [ "Authorization: Bearer ", "Content-Type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://prod.skillsdbnext.com/api/v1/trainings/{id}" payload := strings.NewReader("{\n \"trainingDate\": \"2026-02-11T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Amended evidence note.\"\n}") req, _ := http.NewRequest("PATCH", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } HttpResponse response = Unirest.patch("https://prod.skillsdbnext.com/api/v1/trainings/{id}") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"trainingDate\": \"2026-02-11T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Amended evidence note.\"\n}") .asString(); require 'uri' require 'net/http' url = URI("https://prod.skillsdbnext.com/api/v1/trainings/{id}") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Patch.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"trainingDate\": \"2026-02-11T00:00:00.000Z\",\n \"trainer\": \"J. Instructor\",\n \"evidenceNote\": \"Amended evidence note.\"\n}" response = http.request(request) puts response.read_body 200 400 401 403 404 409 429 500 { "data" : { "id" : "5120" , "person" : { "id" : "42" , "name" : "Welding" }, "skill" : { "id" : "42" , "name" : "Welding" }, "trainingDate" : "2026-02-10T00:00:00.000Z" , "trainer" : "J. Instructor" , "status" : "approved" , "isNotApplicable" : false , "evidenceNote" : "Completed the practical assessment." , "expiresAt" : "2027-02-10T00:00:00.000Z" , "isExpired" : false , "skillVersionId" : "402" , "requestedById" : "91" , "requestedAt" : "2026-02-10T09:00:00.000Z" , "delegatedApproverId" : "88" , "decision" : { "outcome" : "approved" , "decidedById" : "88" , "decidedAt" : "2026-03-02T14:00:00.000Z" , "reason" : null }, "isSuperseded" : false , "createdAt" : "2026-02-10T09:00:00.000Z" } } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com/api-docs/errors/validation-error", "title": "Validation failed", "status": 400, "detail": "limit must be between 1 and 200", "instance": "/api/v1/people", "requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e", "errors": [ { "field": "email", "code": "max_length", "message": "email must be shorter than or equal to 75 characters" } ], "error": "trial_expired", "upgrade_url": "https://app.skillsdb.com/settings/billing" } { "type": "https://help.skillsdb.com --- ## AI Assistant Connections URL: https://help.skillsdb.com/configurations/ai-assistant Quick Summary: The AI Assistant settings let administrators allow employees to connect their own AI assistant to their SkillsDB data. You control whether assistants can only read or also make changes, whether they can run high-impact operations, and you can see and revoke every connection in the company. ​ Overview The AI Assistant feature lets each employee connect their own AI assistant — Claude, ChatGPT, or Microsoft Copilot — to their SkillsDB data. Once connected, the assistant can answer questions and, if you allow it, make changes on the employee’s behalf. Every connection is scoped to that employee’s own permissions. An assistant can never see or do anything the person could not see or do themselves in SkillsDB, and every change it makes runs through the same permission checks and approval steps as the same action taken by hand. This scoping is enforced on every request, so tightening any setting binds already-connected assistants on their very next call. Governance uses three switches, layered so each one only matters once the one above it is on: Setting Controls Default AI Assistant Connections The master switch. Lets employees connect an assistant at all, for read access. Off AI Assistant Writes Whether connected assistants can make changes, not just answer questions. Off AI Assistant — High-Impact Operations Whether assistants can run high-impact operations — anything that notifies whole populations, creates or deactivates sign-in accounts, or permanently destroys data (today: deleting labels, creating or deactivating people, and starting or ending assessment cycles). Off Everything is off by default, so nothing is exposed until an administrator turns it on. Only administrators can change these settings or manage connections. Note: The AI Assistant settings appear only when the feature is enabled for your SkillsDB account. If you do not see the AI Assistants entry on the Settings page, contact your account manager. ​ Prerequisites Before you configure AI assistant access, you need: Permission level : Administrator role Feature availability : The AI Assistant feature enabled for your account Access requirement : Company > Settings , then Manage AI assistant access ​ Turning on AI assistant access The three governance switches are ordinary company settings, so they inherit the same targeting as every other setting — on for everyone, or only for chosen departments, sites, teams, and so on. 1 Open the AI Assistant settings Navigate to Company > Settings . Under AI Assistants , select Manage AI assistant access . 2 Allow connections Turn on AI Assistant Connections . Employees can now connect an assistant with read access to their own data. 3 Allow changes (optional) Turn on AI Assistant Writes to let assistants make changes as well as answer questions. Every change is still bound by the employee’s own permissions and the usual approval steps. This switch appears only after AI Assistant Connections is on. 4 Allow high-impact operations (optional) Turn on AI Assistant — High-Impact Operations to additionally allow the highest-impact actions. This switch appears only after AI Assistant Writes is on. Turning AI Assistant Connections off disconnects every assistant in the company immediately. Turning AI Assistant Writes off leaves reading working and refuses every change. ​ Reviewing and revoking connections The Connected assistants section lists who has connected an assistant and when they last used it, so you can audit access across the company. Each row shows: Column Meaning Person The employee who connected the assistant. Assistant The client that connected — for example, Claude, ChatGPT, or Microsoft Copilot. Access Read only or Read and change , reflecting the scope that connection was granted. Connected The date the connection was created. Last used The date the assistant last made a call, or Never if it has not been used. To end a connection, select Revoke on its row. Revocation takes effect immediately — use it when someone leaves or when a connection should no longer have access. A revoked row is labeled Revoked . Warning: Revoking a connection cannot be undone from here. If the revoke fails, the row stays active and shows an error — try again rather than assuming it worked. ​ Common Questions Can an assistant see data the employee cannot? No. Every connection is scoped to the connecting employee’s own permissions. An assistant can only see and do what that person could see and do themselves in SkillsDB, and every change runs through the same permission and approval checks. What happens to connected assistants when I change a setting? The change binds on the assistant’s next request. Policy is checked live on every call, so turning a switch off — or narrowing who a setting applies to — takes effect immediately for assistants that are already connected, without waiting for them to reconnect. What counts as a high-impact operation? High-impact operations are the actions that affect many people or are hard to reverse: anything that notifies whole populations, creates or deactivates sign-in accounts, or permanently destroys data. Today that means deleting labels, creating or deactivating people, and starting or ending assessment cycles. Everything else an assistant can change stays governed by AI Assistant Writes and the employee’s own permissions. Can I allow assistants for only part of my organization? Yes. The three switches are company settings, so they use the same targeting as other settings — you can turn them on for everyone, or only for specific departments, sites, teams, and so on. ​ Related Articles Organization Settings Configure the other organization-wide settings alongside AI assistant access. API Credentials Compare assistant connections with programmatic API access. Activity Log See how changes are recorded, including changes made by automation. ​ Need More Help? If you need additional assistance: Email support@skillsdb.com Use the in-app help chat Schedule a tr --- ## Career Settings URL: https://help.skillsdb.com/configurations/career-settings Quick Summary: Career Settings control how proficiency grading, training approvals, assessments, and the user dashboard function for each individual career. Settings are configured per career, so different careers can behave differently across your organization. ​ Overview Career Settings is a per-career configuration panel that controls which features are active for a given career in SkillsDB. Each career has its own independent settings, meaning you can enable training approvals for an engineering role while keeping them disabled for a management track, or expose a career dashboard to one group of employees while hiding it from another. There are four main areas to configure in Career Settings: proficiency grading, training dates, assessments, and the user dashboard. Each setting controls a specific capability within the career, and some settings have dependencies on others. For example, assessments can only be enabled when proficiency grading is also enabled. Career Settings are accessible to administrators only. Changes apply immediately to all employees assigned to the career once saved. ​ Prerequisites Before you configure Career Settings, you need: Permission level: Administrator role in SkillsDB Setup requirement: The career must already exist in your Careers Library Access: Navigate to Library > Careers from the left sidebar Managers cannot access or modify Career Settings. Standard users (employees) are not aware of Career Settings — they only see the downstream effects, such as grade columns appearing or the career dashboard becoming accessible. ​ Opening career settings Career Settings can be opened from two places: From the Careers Library table: Navigate to Library > Careers from the left sidebar. Locate the career in the table. Select the settings icon in the career’s row. From the career details panel: Navigate to Library > Careers and select the career name. In the career details panel, select Settings in the top navigation area. The Career Settings page opens, displaying all configurable options for that career. The page header shows the career name and the subtitle: “Configure levels, measurement model, and dashboard for [Career Name].” ​ Manage levels The Manage Levels card appears at the top of the Career Settings page. It displays the current level hierarchy for the career as colored badges (for example, L1 Individual, L2 Manager, L3 Director, L4 VP). Levels create a progression hierarchy within the career, allowing you to define distinct seniority tiers. To add, edit, reorder, or remove levels: Select the Manage Levels button on the Manage Levels card. In the Manage Levels drawer, edit level names directly in the text fields. Each level has a numbered badge (L1, L2, L3, etc.) with a distinct color. Drag levels using the drag handles to reorder them. Levels are arranged in descending order with L1 at the top. Select + Add Level to create a new level at the bottom of the list. Select Save to apply your changes, or Cancel to discard them. Note: You can create as many levels as needed for a career. Level changes take effect immediately once saved and are reflected wherever the career’s level structure is displayed. ​ Proficiency Grading The settings below — Proficiency Grading, Training Dates, and Assessments — are grouped under the Measurement Model section on the Career Settings page. Proficiency grading controls whether skill-level scoring is enabled for the career. When enabled, grade columns appear throughout SkillsDB for skills within this career — including the skills matrix, team views, and individual employee profiles. Proficiency data is also included in search results and analytics reports. Default: On When proficiency grading is disabled: All grade columns (benchmark, manager grade, employee grade) are hidden across all views for skills in this career. Proficiency data for this career is excluded from search results and analytics. Assessments are automatically disabled (assessments require proficiency grading). Grade bars and grade indicators are not displayed on employee profiles. When proficiency grading is re-enabled , previously hidden grade columns and data become visible again. No data is lost when proficiency grading is toggled off. Important: Disabling proficiency grading automatically disables assessments for the career. Re-enabling proficiency grading does not automatically re-enable assessments — you must turn assessments back on separately. ​ Training Dates Training dates enables training approvals and training visibility for the career. When enabled, employees can request training approval for skills within the career, and those skills appear in the training matrix report. Default: Off When training dates are enabled: Employees can request training approval for skills in this career. Career skills appear in Team > Training > Training Matrix . Training status columns (training status, training expiration, expiration timeline) appear in the employee detail view. The Training Timeline configuration fields and the Bulk Update Skill Training Settings tool become available within Career Settings. When training dates are disabled: Training approval requests are hidden for skills in this career. Career skills are excluded from the training matrix. Training-related columns are hidden from all views. ​ Training timeline When training dates are enabled, a Training Timeline section appears within Career Settings. The training timeline sets the expected duration for an employee to complete training approval for all skills in the career. The timeline is configured using three optional numeric fields: Field Description Days Number of days component of the expected training duration Months Number of months component Years Number of years component All three fields are optional. The combined value (for example, 1 year, 6 months, 15 days) is displayed in the employee detail view as a training progress indicator, showing whether an employee is on track, upcoming, --- ## Favorites URL: https://help.skillsdb.com/configurations/favorites Quick Summary: Favorites let you pin any page in SkillsDB to a dedicated section of the left navigation. Select the star icon in the page header to save a page with its current filter, sort, and display state. Personal favorites are visible only to you. Administrators can pin favorites for everyone in the company or for selected groups. ​ Overview Favorites are named bookmarks to pages in SkillsDB — plus the exact filter, sort, and display state those pages were in when you saved them. They appear as buttons in a dedicated Favorites section at the top of the left navigation, giving you quick access to the views you use most. Every user can create personal favorites, visible only to them. Administrators can create admin favorites that appear in the sidebar for every user in the company, or for a selected subset of users (for example, everyone in a specific business unit or department). This makes favorites both a personal productivity tool and an org- or company-wide navigation tool — admins curate the most important pages and views, and individuals supplement with their own shortcuts. Because favorites capture both the URL and the extended display state, they preserve configurations that would otherwise be lost on reload — things like column selections, chart types, grading tab selection, and applied filters. Opening a favorite is identical to navigating back to that page in the exact state you saved it. Favorites complement, but are different from, Saved Views . A favorite is a shortcut in the Favorites section of the sidebar. A saved view becomes a named sub-page under the relevant parent page. Use favorites when you want quick access to any page or configuration; use saved views when you want a specific configuration to appear as a permanent sub-page under a parent section. ​ Prerequisites Before creating favorites, you need: Permission level : Any user role to create personal favorites; administrator role to create admin favorites visible to others Access requirement : Any SkillsDB page — favorites work on pages with or without filters applied ​ The Favorite Button The favorite button appears as a star icon in the page header area of most SkillsDB pages. The icon state shows whether the current view is already favorited: Icon state Meaning Outline star The current page and state is not currently a favorite Filled star The current page and state matches an existing favorite A favorite is matched to the current page by both its path (for example, /team/people ) and its URL parameters (filters and sort). This means the same page can have multiple favorites saved at different filter states, and each one shows a filled star only when its exact configuration is active. ​ Creating a Personal Favorite Any user can create a personal favorite on any page. Personal favorites are visible only in your own sidebar and appear with a yellow star icon in the Favorites section. 1 Apply the state you want to save Navigate to the page you want to favorite. Apply any filters, sorts, column selections, or display settings you want to preserve. 2 Open the save modal Select the star icon in the page header. A modal opens with fields to configure the new favorite. 3 Name the favorite Enter a display name in the name field. The display name is what appears in the Favorites sidebar section, so choose something that makes the purpose immediately clear — for example, My Team — Training Overdue or Engineering Careers . 4 Confirm visibility Leave the visibility option set to Only Me . This is the default for all users. 5 Save Select the save button. The favorite is created immediately and appears in the Favorites section of the left navigation. The star icon on the page switches from outline to filled, confirming that the current view is now favorited. ​ Creating an Admin Favorite Administrators can create favorites that appear in the sidebar for other users — either all users in the company or a specific subset based on org structure. Admin favorites appear with a blue star icon to distinguish them from personal favorites. 1 Apply the state you want to save Navigate to the page you want to share as a favorite and apply the filters, sorts, column selections, or display settings that every targeted user should see. 2 Open the save modal Select the star icon in the page header. 3 Name the favorite and choose visibility Enter a display name , then change the visibility option: Option Who sees the favorite Only Me Only you — a personal favorite All People Every user in the company Select Groups Only users in the business units, divisions, departments, teams, sites, shifts, cities, states, countries, or business regions you select 4 For Select Groups, target the audience If you chose Select Groups , an org structure picker appears. Select one or more groups from any dimension. SkillsDB shows a live count of users who will receive the favorite as you change the selection. 5 Save Select the save button. The admin favorite is created and appears in the Favorites sidebar section for every targeted user the next time they load the app. Warning: Admin favorites appear for users immediately on their next navigation — users cannot remove an admin favorite from their own sidebar. Only an administrator can delete it. Confirm the name and targeting before saving. ​ Using Favorites Once created, favorites appear in a dedicated Favorites section at the top of the left navigation, with a star icon next to each entry. Select any favorite to navigate directly to the page it points to — SkillsDB applies the saved filters, sort order, columns, and extended display state automatically. The currently active favorite is highlighted in the navigation while you are on that exact page and state. Changing filters or navigating away un-highlights the favorite but does not remove it. Note: If you apply new filters or sorts on a page that matches a favorite, the star icon on the page header switches back to outline — this means the current state --- ## Labels URL: https://help.skillsdb.com/configurations/labels Quick Summary: Labels are color-coded tags you apply to skills, careers, training resources, and certifications to organize, filter, and group records across SkillsDB. Admins manage the label library; managers and employees can apply labels to records within their access. ​ Overview Labels in SkillsDB are a flexible tagging system that lets your organization categorize and cross-reference records across the platform. A label is a named, color-coded tag that can be attached to four entity types: skills , careers , training resources , and certifications . Once applied, labels appear throughout SkillsDB in tables, grids, and filters — giving admins, managers, and employees a consistent way to group and locate related content. Labels support a parent-child hierarchy . A top-level label (for example, “Compliance”) can have sub-labels (for example, “Safety”, “Data Privacy”, “Financial”). Sub-labels can themselves have further children. This means your organization can build a structured taxonomy that reflects how you think about skills and roles — without flattening everything into a single alphabetical list. Each label carries a color that appears as a small circle indicator wherever the label is displayed. Colors help users visually distinguish labels at a glance, particularly in dense tables and grids. Administrators manage the full label library — creating, editing, reordering, and deleting labels. Managers can apply and remove labels from records within their access. Employees can add labels to their own profile entries for skills, certifications, and training. ​ Prerequisites Before creating or managing labels, ensure you have: Permission level: Administrator role in SkillsDB Access required: Navigate to Labels in the left sidebar under the Company section Note: The Labels navigation item is only visible to users with administrator access. Managers and employees interact with labels through label selector components embedded in skills, career, training, and certification pages — not through the dedicated Labels management page. ​ Understanding Label Structure Labels in SkillsDB are organized as a hierarchical tree . Every label is either a top-level label (no parent) or a sub-label (child of another label). There is no enforced limit on tree depth — a label hierarchy can be as shallow or as deep as your organization requires. Level Description Example Top-level label A root category with no parent ”Compliance”, “Technical Skills”, “Leadership” Sub-label A child of a top-level or deeper label ”Safety” (under “Compliance”), “Python” (under “Programming”) Deeper sub-label A child of a sub-label ”OSHA Certification” (under “Safety” under “Compliance”) When a top-level label is deleted, its sub-labels are permanently deleted along with it. When a sub-label is deleted, only that sub-label is removed; its siblings and the parent label are unaffected. Each label has a name (up to 50 characters) and a color (a hex color selected from the color picker). The color defaults to blue if none is chosen. ​ Managing the Labels Library To access the labels library, navigate to Company > Settings and select Configure labels on the Labels row. There is no Labels item in the sidebar — the page opens with a Company > Settings > Labels breadcrumb. The Labels page displays all labels in your organization as a hierarchical tree. Top-level labels appear at the root; sub-labels are nested beneath their parents and can be expanded or collapsed. ​ Label tree features Each label row in the tree includes: Color indicator — A small colored circle representing the label’s color. Select the circle to open the color picker and change the color inline. Label name — Selectable to navigate to the label’s detail page. Sub-label count — A blue badge showing how many direct child labels this label has. Visible only if the label has at least one child. Expand/collapse arrow — For labels with sub-labels, select the arrow to expand or collapse the nested tree. Drag handle — Hover over a row to reveal the drag handle on the left. Use it to reorder labels within the tree. Action buttons — Hover over a row to reveal three action buttons: Edit , Delete , and Add a sub-label . ​ Searching labels A search input at the top right of the page filters the label tree by name in real time. Enter any part of a label name to narrow results. The tree updates to show matching labels and their parent labels for context. If no labels match your search, the page displays: “No results for ‘[search term]’. Try a different search term.” ​ Creating Labels Administrators can create new labels at the top level or as sub-labels of an existing label. ​ Creating a top-level label Navigate to Labels in the left sidebar. Select Add Label in the top right of the page. In the Add Label dialog, complete the following: Field Required Description Label Name Yes A unique, descriptive name for the label. Maximum 50 characters. Color No A color selected from the inline color picker. Defaults to blue if not set. Select Add . When the label is created successfully, a confirmation toast appears: “Label added successfully.” The label appears in the tree at the bottom of the top-level list. ​ Creating a sub-label Sub-labels can be created from the labels tree or from within a label’s detail page. From the labels tree: Navigate to Labels in the left sidebar. Hover over the parent label where you want to add a child. Select the Add sub-label icon that appears on hover. In the Add Sub Label dialog, enter a Sub Label Name and optionally select a color. Select Add . From the label detail page: Navigate to a label’s detail page by selecting its name in the tree. Select Add Sub Label in the top right of the page. Complete the name and color fields, then select Add . Tip: Use sub-labels to create meaningful taxonomies that match how your organization already categorizes skills and roles. For example, a top-level “Technical Skills” label with sub-labels for “Frontend”, “Backend”, --- ## Page Settings URL: https://help.skillsdb.com/configurations/page-settings Quick Summary: Page Settings are the on/off controls on Company > Settings that decide which sidebar sections your users see and which platform behaviors are active. Administrators change them; the effect is immediate and organization-wide. ​ Overview Page Settings are the toggle controls on the Company > Settings page. Where the structural settings covered in Organization Settings define the data SkillsDB operates on — grades, org structure, training attributes — Page Settings define what your users can see and do with that data. There are two kinds of toggle. Simple switches turn a single behavior on or off, such as hiding manager grades from employees or enabling system emails. Grouped toggles open a modal containing several related switches, such as the per-section visibility controls for the Library, Profile, and Team navigation groups. Visibility toggles are how most organizations phase SkillsDB in. A company that has not yet built its certification library can hide Library > Certifications and Profile > Certifications so employees never see an empty page, then switch both on when the library is ready. Because the toggles drive both the sidebar and the page-level access check, a hidden section is genuinely unreachable rather than merely absent from the menu. Only administrators can view or change Page Settings. The settings apply to every user in your SkillsDB instance — they are organization-wide, not per-user or per-team. Note: Users with the GlobalAdmin, Admin, or Full Access role always see every navigation section regardless of the visibility toggles. If you hide a section and can still see it, check your own role before assuming the setting did not save. ​ Prerequisites Before you begin, you need: Permission level: Administrator role Access: Navigate to Company > Settings in the left sidebar ​ Hiding Manager Grades From Employees The Hide Manager Grades switch prevents all employee users from seeing their manager’s assessment of their skills anywhere in SkillsDB. When you enable Hide Manager Grades , employees no longer see the manager grade on their skills profile, in assessments, or in any matrix view. Employees are also not notified when a manager completes an assessment of them. When you disable it, manager grades become visible to employees again — no data is lost while the setting is on, only hidden. Organizations typically enable this setting during a calibration cycle, so managers can complete their assessments without employees reacting to in-progress grades, then disable it once the cycle closes and results are ready to share. To change it, navigate to Company > Settings and toggle the Hide Manager Grades switch. The change takes effect immediately for all users. ​ Enabling Skill Flags The Enable Skill Flags switch activates the skill flags feature for all users. When you enable skill flags, employees can flag skills as Focus or Interest from their profile page and from inside assessments. Managers can flag employee skills as Focus , Expert , or Mentor . Employees cannot alter a Focus flag that was set by their manager. When you disable skill flags, flag controls disappear from profiles, assessments, and matrices. Existing flag assignments are retained in SkillsDB and reappear if you re-enable the setting. The Expert flag is the one with functional consequences: an Expert can approve training requests for the skills they are flagged on. See Skill Flags for how to configure flag types and trainer designations. To change it, navigate to Company > Settings and toggle the Enable Skill Flags switch. ​ Controlling Library Visibility The Hide Library Sections setting controls which of the four Library sections appear in the sidebar. Select Configure Visibility Of Library Section to open the Manage Library Visibility modal, which contains one switch per section: Switch Controls Skills Library > Skills — the organization-wide skills catalog Certifications Library > Certifications — the certification catalog Training Library > Training — the training resource library Careers Library > Careers — career definitions and skills matrices When you switch a section off, it is hidden from every non-administrator’s sidebar and the corresponding pages become inaccessible to them. If you switch all four off, the Library group disappears from navigation entirely for those users. Administrators, GlobalAdmins, and Full Access users continue to see all four sections regardless of these switches, so you can keep building a library while it is hidden from everyone else. Select Close when you are finished. Changes save as you toggle — there is no separate save step. ​ Controlling Profile and Team Section Visibility The Hide Profile & Team Sections setting controls which items appear under the Profile and Team sidebar groups. Select Configure Visibility Of Profile & Team Sections to open the Manage Profile & Team Visibility modal. Profile switches Team switches Switch Controls Assessments Profile > Assessments — the user’s own assessments Certifications Profile > Certifications — the user’s own certifications Learning Plan Profile > Learning Plan — the user’s own learning plan Surveys Profile > Surveys — surveys assigned to the user Files Profile > Files — the user’s uploaded documents Profile > Skills has no switch. It is the universal landing page after sign-in, so hiding it would lock users out of the application on login. Switch Controls Skills Team > Skills — team skills analysis and Overall Training Status Assessments Team > Assessments — manager assessments Certifications Team > Certifications — team certification tracking Training Team > Training — All Activity, Training Matrix, and Expirations People Team > People — the team roster If you switch off every item in a group, that group is removed from navigation for affected users. As with library visibility, administrators and Full Access users always see every item. Important: The Team group also requires a manager-or-higher role. Switc --- ## People Flags URL: https://help.skillsdb.com/configurations/people-flags Quick Summary: People Flags are colored labels that administrators assign to individuals to categorize them across your organization. SkillsDB includes three built-in potential flags, and you can create unlimited custom flags to match your own categorization needs. ​ Overview People Flags are administrator-defined labels attached to individual employees to mark meaningful attributes — for example, talent potential levels, project availability, leadership readiness, or any other category relevant to your organization. Once assigned, flags appear as colored badges on a person’s profile and in people tables, making them immediately visible to anyone with access to that person’s record. SkillsDB includes three system-default flags for talent potential assessment that are available immediately without any configuration. Administrators can supplement these with any number of custom flags, each with a unique name, description, and color. People Flags are distinct from Skill Flags. People Flags are applied to individuals and describe attributes of the person. Skill Flags are applied to a person’s relationship with a specific skill and describe their level of expertise or designation for that skill (for example, Expert or Mentor). See Skill Flags for information on that feature. Only administrators can create, edit, delete, and assign People Flags. Managers can view flags applied to their direct reports but cannot modify them. ​ Prerequisites Before managing People Flags, you need: Permission level : Administrator role Access : Navigate to Settings > Flags > People Flags tab ​ Understanding People Flags ​ System flags SkillsDB includes three system-default People Flags that are pre-configured and available to all organizations. These flags cannot be edited or deleted, but they can be disabled if your organization does not use them. Flag Color Purpose High potential Green Marks individuals demonstrating exceptional growth potential and readiness for advancement Moderate potential Yellow Marks individuals showing steady growth potential with room for development Low potential Red Marks individuals showing limited growth potential in their current role System flags are labeled System in the flags list and their name, description, and color cannot be changed. ​ Custom flags Administrators can create unlimited custom flags with a name, optional description, and color of their choosing. Custom flags are fully editable after creation and can be deleted at any time. Custom flags support any categorization that matters to your organization — for example: Project availability ( Available , On Bench , Deployed ) Specialist designations ( AWS Certified , Six Sigma Black Belt ) Development programs ( Mentoring Program , Leadership Track ) Succession planning ( Successor – Director , Succession Candidate ) ​ People Flags vs Skill Flags People Flags and Skill Flags are two distinct systems that exist side by side in SkillsDB. Understanding the difference helps ensure you apply the right tool. People Flags Skill Flags Applied to A person A person’s specific skill Describes An attribute of the individual An attribute of the person-skill relationship Examples High potential, Available, On Bench Expert, Mentor, Focus, Interest Managed at Settings > Flags > People Flags tab Settings > Flags > Skill Flags tab Assigned via People tables or person profile Skills matrix or person’s skill record Use People Flags to describe who a person is organizationally. Use Skill Flags to describe someone’s standing or relationship to a specific skill. ​ Managing People Flags All People Flag management is done from Settings > Flags . Select the People Flags tab to view and manage the full list of flags for your organization. The flags list displays each flag’s name, description, color, and enabled status. Drag handles on the left allow you to reorder flags. System flags are labeled System and have no edit or delete icons, but their Enabled checkbox still works and they can be dragged to reorder. ​ Creating a custom flag Navigate to Settings > Flags and select the People Flags tab Select Add Flag In the Add new people flag modal, enter the following: Flag name (required) — Up to 30 characters Description (optional) — Up to 100 characters; shown as a tooltip when hovering over the flag badge Color — Enter a hex color code (for example, #3B82F6 for blue); defaults to gray if left blank Select Save The new flag appears at the bottom of the flags list and is enabled immediately. You can drag it to any position in the list. Tip: Choose colors that are visually distinct from one another and from the system flags. High-contrast colors make flags easier to scan in large people tables. ​ Editing a custom flag Navigate to Settings > Flags > People Flags tab Select the edit icon (pencil) next to the flag you want to update In the Edit people flag modal, update the name, description, or color Select Save Changes take effect immediately. Any person who already has the flag assigned will see the updated name, description, and color on their record. Note: System flags (High potential, Moderate potential, Low potential) cannot be edited. The edit icon is not available for system flags. ​ Enabling and disabling flags Each flag has an Enabled toggle that controls whether it can be assigned to new people. Enabled — The flag is active and appears in the flag assignment dropdown when editing a person’s flags. Disabled — The flag is hidden from the assignment dropdown. It cannot be applied to new people, but existing assignments are preserved. The flag badge continues to appear on people who already have it assigned, marked as Inactive . To toggle a flag, select its Enabled checkbox in the flags list. The change takes effect immediately. Disabling a flag is the recommended approach when you want to retire a flag temporarily without losing existing assignment data. Deleting a flag is permanent and removes it from all people. ​ Reordering flags The order of --- ## Saved Views URL: https://help.skillsdb.com/configurations/saved-views Quick Summary: Saved views capture the current filter, sort, and display state of any page and make that state available as a named option in the page-header view menu. Only administrators can create saved views. Admins choose whether a view is visible to all users in the company or only to selected org groups. ​ Overview A saved view is a named page configuration that appears in the page-header view menu. When you select a saved view, SkillsDB loads the parent page with the exact filters, sort order, column selections, and display settings the admin saved — no re-configuration required. Only administrators can create saved views. An admin applies the desired state on any page that supports filters or sorting, saves the state with a display name, and chooses who can see the view. Users who fall within the chosen audience can select the saved view from the page-header view menu. Saved views complement Favorites , but they serve different purposes: A favorite is a starred entry in the dedicated Favorites section at the top of the sidebar. Any user can create personal favorites; admins can create admin favorites for the company. A saved view is a named option in the parent page’s view menu. Only admins can create saved views, and they can target the view to all users or to selected groups. Use favorites for top-level shortcuts. Use saved views when a specific configuration should appear as a reusable view of a page for a defined audience — for example, an Onboarding — Week 1 view under Team > People , or Frontline — Overdue Training under Team > Skills . ​ Prerequisites Before creating or managing saved views, you need: Permission level : Administrator role in SkillsDB Access requirement : A SkillsDB page that supports filtering, sorting, or display configuration — open the page’s Display menu to find Save as Page ​ Opening Save as Page Open Display in the page header, then select Save as Page . Administrators can save the current filters and display settings, including column changes. ​ Creating a Saved View 1 Apply the state you want to share Navigate to the page you want to save. Apply the filters, sort, column selections, and display settings every targeted user should see when they open the view. 2 Open the Save as Page modal Open Display , then select Save as Page . The Save as Page modal opens. 3 Enter a display name Type a display name in the name field. The display name is what users see in the breadcrumb view selector for that page, so choose something that clearly describes the view’s purpose — for example, Overdue Training or Field Engineers — California . 4 Choose an audience Select one of the two audience options: Option Who sees the saved view All People Every user in the company Select Groups Only users in the business units, divisions, departments, teams, sites, shifts, cities, states, countries, or business regions you choose For Select Groups , an org structure picker appears. Select one or more options in each relevant group field. Checked options remain selected; select an option again to remove it. Group selections retain their identity when their names change. A profile count appears when available; selections containing states show audience text instead. 5 Save Select Add Page . SkillsDB creates the saved view and displays a success toast — “Page saved for all users” or “Page saved for targeted groups.” The view becomes selectable from the page’s breadcrumb view selector for targeted users the next time they load the app. Warning: Saved views appear in the breadcrumb view selector for targeted users immediately on their next navigation. Users cannot hide or remove a saved view that was targeted to them — only an administrator can delete it. Confirm the audience and naming before selecting Add Page . ​ Using a Saved View Open the view menu beside the breadcrumbs and select a saved view to load the parent page with all of the saved filters, sort order, columns, and display settings pre-applied. Because saved views store URL parameters plus extended display state, they preserve configurations that would otherwise reset on reload — such as column widths, chart type selections, and grade tab selections. Note: Underlying data in the page (the list of people, skills, grades, training records) remains live and current. The saved view only fixes the filter and display configuration — not the content that meets those criteria. ​ Resetting a View After opening a saved view, you can adjust filters or display settings temporarily. Display > Reset restores that saved view’s settings. It does not replace the saved configuration with the page default. To switch to the page default, use the view menu. Administrators can also choose Set default for all from Display and select All People or Select Groups . ​ Saving numeric filters Where a numeric filter is available, choose ≥ , ≤ , = , or between , enter the value or bounds, and select Apply . Between includes both endpoints. Clear removes the filter; Escape closes an unfinished edit. Saved views preserve these filters. Existing saved strict above/below and not-equal filters keep their original meaning. ​ Managing Saved Views Administrators have a dedicated settings page for reviewing and removing saved views across the organization. To open the management page: Navigate to Settings from the gear icon or settings menu. Select Saved Views . The page has two tabs: Tab What it shows Saved Pages All saved views across the company, grouped by parent page. Each row shows the display name, the parent path, targeting (All People or a list of selected groups), and actions to open in a new tab or delete. Saved Defaults The default page state configured for each page (what users see when they first navigate to a page with no saved view selected). Each row can be reset to restore the system default. Use the search bar to filter by display name or path. Use the type filter to show only company-wide views, only population-targeted views, or all view --- ## Organization Settings URL: https://help.skillsdb.com/configurations/settings Quick Summary: The Settings area gives administrators full control over the structural foundations of SkillsDB — including how skills are graded, who can search for what, how training resources are categorized, how your organizational hierarchy is defined, and other platform-wide behaviors. ​ Overview The Settings area is the administrative backbone of SkillsDB. Administrators define the organizational rules and structures that underpin every other feature in the platform — from how proficiency is measured to which users can find each other in search. Settings is accessible from Company > Settings in the left sidebar. The page is organized into two types of configuration: Toggle settings control on/off behaviors like hiding manager grades, enabling skill flags, and enabling system emails. These are covered in Page Settings . Structural settings link to dedicated sub-pages where you build and manage structured data — like your grading scale, organizational hierarchy, search permissions, and training library metadata. This article covers the structural configuration areas accessible from the Settings page: Grading Scale , Search Permission , Training Library , Org Structure , Files , Skill Assignment Dates , and Saved Defaults & Saved Pages . Note: All settings in this area are organization-wide and apply to every user in your SkillsDB instance. Only administrators can access and modify settings. ​ Prerequisites Before you begin, you need: Permission level: Administrator role Access: Navigate to Company > Settings in the left sidebar ​ Configuring the Grading Scale The grading scale defines the proficiency levels used throughout SkillsDB — in self-assessments, manager assessments, skills matrices, and gap analysis. Every skill assessment in your organization uses the grades you define here. Navigate to Company > Settings , then select Grading Scale to open the Grading Scale Settings page. ​ Understanding grade structure The grading scale table has four columns: Column Details Grade A numeric value (0–10). Grade 0 is a special “not yet assessed” grade. Description Contains two parts: a short description (the primary label, maximum 100 characters) and an optional extra description (additional details or examples for the grade level). Status Shows whether the grade is currently in use. See the grade status reference below. Actions Delete button for unused grades. Grade 0 has an active/inactive toggle instead. Important: Once any grade has been used in an assessment, that grade’s number is permanently locked and cannot be edited or deleted. You can always update the descriptions of a grade at any time, even after the grade has been used. ​ Adding a new grade 1 Open the grading scale Navigate to Company > Settings , then select Grading Scale . 2 Add a new grade Select + Add new Grade . A confirmation modal appears showing the next available grade number (for example, “Are you sure to add new grade level 6?”). 3 Enter descriptions Enter a Short Description (required, maximum 100 characters). Optionally enter an Extra Description to provide additional details or examples for this grade level. 4 Confirm Select Confirm to save the new grade. The new grade immediately appears in the grading scale table and becomes available for use in assessments throughout SkillsDB. ​ Editing an existing grade Click directly on any description field in the table to start editing — an edit icon appears on hover. Press Enter or click outside the field to save. Press Escape to cancel. Descriptions are always editable, even for grades that are in use. Grade numbers that are in use cannot be changed. ​ Deleting a grade Grades can only be deleted if they have never been used in an assessment. To delete a grade, select the delete icon in the Actions column for that row. Grade 0 cannot be deleted. It can only be deactivated (see below). ​ Deactivating grade 0 Grade 0 is the system’s default “not yet assessed” state. It cannot be deleted, but it can be deactivated to hide it from assessments and grading views. Toggle the switch in the Actions column for Grade 0 to deactivate or reactivate it. When grade 0 is deactivated, it is not shown as a selectable option in assessments. ​ Grade status reference Status Indicator Meaning Not in Use Green dot Grade exists but has never been used in an assessment. Fully editable and deletable. In Use Orange dot Grade has been used in at least one assessment. Grade number is locked; descriptions remain editable. Inactive Gray dot Grade 0 only. Deactivated and hidden from assessment options. Tip: Set up your complete grading scale before launching assessments. Once grades are used, their numbers are locked. Most organizations use a 1–5 scale, though SkillsDB supports up to grade 10. ​ Configuring Search Permissions Search Permissions control which user roles can search for people within SkillsDB and what information they can filter by. These settings let you balance visibility and privacy across your organization. Navigate to Company > Settings , then select Search Permission to open the Search Permissions page. ​ Understanding roles and access levels Search permissions are configured across four columns representing security groups: Role Description Admin Full access — all settings are locked and cannot be changed Full Access Always has full people search access — cannot be restricted Manager Configurable; typically has chain of command visibility Employee Configurable; typically limited or no people search access ​ Permission types The permissions table contains the following rows: Permission type Description Enable Search Master toggle that enables or disables overall search access for each role. Shown as a checkbox. People Search Access Controls the scope of people search results. Options vary by role. Minimum to Appear in Results When People Search Access is set to Above Grade , specifies the minimum proficiency grade a person must have to appear in search results. Skill Grades Filter F --- ## Skill Flags URL: https://help.skillsdb.com/configurations/skill-flags Quick Summary: Skill flags are colored labels you apply to people at the skill, section, or career level to mark specific designations — such as subject matter experts or approved trainers. Admins create and configure flags from the Flags Configuration page. Managers apply flags to their team members. ​ Overview Skill flags are designations that mark a person’s relationship to one or more skills. A flag might identify someone as the go-to expert for a skill, an approved trainer who can sign off on training requests, a focus area for development, or any other custom designation that matters to your organization. Flags can be applied at three different scopes — a single skill, an entire section within a career, or an entire career — allowing broad designations to cascade naturally without requiring individual assignments for every skill. Admins create and manage the available flag types from Company > Settings > Flags . Managers apply those flags to their direct reports from within career and skill views. Employees can view flags applied to their own skills but cannot create or modify flag assignments. Flags appear throughout SkillsDB: in skill profiles, in the Flag Matrix view for a career or section, and as a search filter — allowing managers and admins to quickly find flagged employees. ​ Understanding Flag Scope When a flag is applied to a person, it is assigned at one of three scope levels. Each level determines which skills the flag is visible on for that person. Scope Description Example Skill The flag applies to one specific skill ”Expert” applied to Python only Section The flag applies to all skills within a career section ”Expert” applied to all skills in the “Backend Development” section Career The flag applies to all skills across an entire career ”Expert” applied to all skills in the “Software Engineering” career When viewing the Flag Matrix, flag sources are color-coded: Direct (skill-level assignment) — indigo Section (inherited from a section assignment) — purple Career (inherited from a career assignment) — pink A person can hold multiple flags for the same skill — for example, having both an Expert flag from a career-level assignment and a separate Mentor flag applied at the skill level. ​ Creating a Skill Flag Administrators can create custom skill flags to represent any designation used in your organization. New flags are immediately available for use once created. To create a new skill flag: Navigate to Company > Settings > Flags Select the Skill Flags tab Select Add Flag In the Add new skill flag modal, enter a Flag Name (required, maximum 100 characters) Optionally enter a Description (maximum 500 characters) Select a Color using the color picker — the color will appear as the flag’s badge color throughout SkillsDB Select Add Flag The new flag appears in the Skill Flags list and becomes immediately available for assignment across SkillsDB. New flags are enabled by default with Trainer Permission off. Note: After creating a flag, use the inline Enabled and Trainer Permission checkboxes on the flag row to configure those settings. They cannot be set during initial creation. ​ Editing a Skill Flag Administrators can update the name, description, and color of any custom skill flag. System default flags cannot be edited. To edit a custom skill flag: Navigate to Company > Settings > Flags Select the Skill Flags tab Select the edit icon (pencil) on the flag you want to update In the Edit skill flag modal, update the Flag Name , Description , or Color as needed Select Save Changes Changes take effect immediately. Any existing flag assignments retain the updated name and color. Note: System default flags display a System badge instead of edit and delete icons. The name, description, and color of system defaults cannot be changed. The Enabled checkbox is available on every flag, including system defaults; only the Trainer Permission checkbox is hidden on system defaults. ​ Enabling and Disabling Flags Each flag has an Enabled checkbox that controls whether the flag appears in the assignment dropdown throughout SkillsDB. Disabling a flag hides it from use without deleting it or removing existing assignments. To enable or disable a flag: Navigate to Company > Settings > Flags Select the Skill Flags tab Check or uncheck the Enabled checkbox on the flag row When you disable a flag, it is immediately hidden from all flag selection dropdowns and is no longer available for new assignments. Existing assignments to people are preserved and remain visible in the Flag Matrix and skill profiles. When you re-enable the flag, it reappears in dropdowns and all historical assignments are restored without any reassignment required. Important: Disabling a flag does not remove it from people who already have it. It only prevents new assignments. Re-enabling the flag restores full visibility. ​ Managing Trainer Permission The Trainer Permission toggle grants the holder of a flag the ability to approve training requests for the skills they are flagged on. This integrates directly with SkillsDB’s training approval system. When a person holds a flag with Trainer Permission enabled, they receive training approval requests in their Inbox for any skills covered by that flag assignment. To enable or disable Trainer Permission on a flag: Navigate to Company > Settings > Flags Select the Skill Flags tab Check or uncheck the Trainer Permission checkbox on the flag row When Trainer Permission is enabled on a flag, a Trainer badge appears on the flag row to confirm the setting is active. Note: The Trainer Permission checkbox appears only on custom flags. The Expert system flag ships with Trainer Permission already enabled — it shows a Trainer badge — but the setting cannot be changed on system defaults. Changes to Trainer Permission take effect immediately for all current holders of that flag. ​ Reordering Flags The order flags appear in the Skill Flags list determines the order they appear in flag selection --- ## Activity Log URL: https://help.skillsdb.com/core-concepts/activity-log Quick Summary: The Career Activity Log is a time-stamped, filterable record of every change made to a career. Administrators open it from the Careers library to see who assigned people, edited skills, changed training settings, or updated levels — and can trigger downstream actions like notifying affected users or forcing training re-approval directly from the log. ​ Overview The Activity Log gives administrators a complete audit trail of every change that happens to a career. Every time someone is assigned to the career, a skill is added or edited, a training setting is updated, a level is changed, or a label is applied, the event is captured with a timestamp, the person who performed the action, and the details of what changed. The log is purpose-built for two jobs: Accountability. Answer the question “who changed what, when?” during an audit, an investigation, or a customer-support ticket. Downstream action. Some changes (like editing a skill or a training setting) ripple out to people assigned to the career. The log provides built-in actions to notify those people or force training re-approval without leaving the page. Career activity is administrator-only. Managers and employees do not have access to the Activity Log for a career. Note: A company-wide activity log covering the entire organization is on the SkillsDB roadmap. Until it ships, the Activity Log is scoped to a single career at a time — open the log for any career from the Careers library. ​ Prerequisites Before you open the Activity Log, you need: Permission level: Administrator role in SkillsDB Setup requirement: At least one career in your Careers library Access: Navigate to Library > Careers from the left sidebar Non-admin users who navigate to a career activity URL are redirected back to the Careers library. ​ Opening the Activity Log 1 Open the Careers library Navigate to Library > Careers from the left sidebar. 2 Open a career's activity page Select the career whose activity you want to review. From the career details panel, select the Activity action. The URL changes to /manage/careers/activity/[careerId] and the breadcrumb reads Activity / [Career Name] . 3 Switch between careers The breadcrumb includes a career picker — select the combobox next to the career name to jump to any other career’s activity log without navigating back to the library. ​ Reading the Log The Activity Log is a table of events, newest first. Each row captures one discrete change. ​ Columns Column Description Event type A colored badge summarizing the category — People, Skill, Section, Training, Level, Label, Flag, and others. Badge color indicates the category. Event description A human-readable summary of what happened, with the relevant entity (person, skill, section, etc.) named inline. Performed by The administrator who made the change, shown with their name, email, and avatar. Events made through the API display an API badge. A career assignment made by a journey is attributed to that journey, shown as a badge you can select to open the driving journey. Performed at The date and time the change occurred. Affected count For bulk actions — the number of people, skills, or related items touched by the single event. Actions Any follow-up actions available for that event, such as Notify or Force re-approval . ​ Event categories Activity events fall into category groups, each with its own badge color: Category Badge color Example events People Blue Person assigned to the career, person removed, bulk assign, bulk remove Skill Green Skill added, skill edited, training setting changed on a skill Training Cyan Learning resource linked, unlinked, or updated Section — Section created, renamed, reordered, or removed Level — Level created, renamed, reordered, or removed Label — Label applied to the career, label removed Flag — Skill flag or career-level flag assigned or removed Note: Bulk actions (like assigning 50 people at once) are collapsed into a single log entry with an Affected count so the log stays scannable. Expand the row to see the individual people or items involved. ​ Filtering and Searching The Activity Log supports filtering to help you zero in on the events that matter. Date range — use the date picker to scope the view to a specific window (the default lookback is a broad recent range). Options include common ranges like the last 7 days, last 30 days, and this month, plus a custom start/end. Event type — filter to one or more event categories (People, Skill, Training, etc.) when you only want to see activity of a certain kind. Performed by — filter by the administrator who made the changes, useful for reviewing one person’s activity. Combine filters freely. The table updates as you change each filter, and the result count in the header reflects the filtered set. ​ Taking Action from the Log Some events have a direct impact on users assigned to the career — for example, editing a skill’s name or its training requirements. The Activity Log lets administrators act on those events without leaving the page. ​ Notify users The Notify action sends an email to a selected audience explaining that a change occurred. Available targets: Target Who receives the notification All assigned Every user currently assigned to the career All assigned, without training approval Users who have not yet received training approval for the affected skill All assigned, with training approval Users who have training approval (to let them know the definition changed) All assigned, awaiting training approval Users with submitted-but-pending training approval requests Experts only Users flagged as Expert on the affected skill Notifications are sent immediately and recorded in the log with an Email Sent indicator. ​ Force training re-approval The Force re-approval action resets training-approval status on an affected skill so users must submit training approval again. Available targets: Target Who is forced to re-approve All assigned, with training approval U --- ## Analytics & Reporting URL: https://help.skillsdb.com/core-concepts/analytics-and-reporting Quick Summary: SkillsDB analytics surfaces skills data, training completion, and assessment progress in one platform. Admins have full access to all analytics areas; managers can access team-level reporting for their direct reports and organizational hierarchy. ​ Overview SkillsDB provides a suite of built-in analytics and reporting tools that help administrators and managers make data-driven decisions about workforce development. Rather than exporting raw data and building reports manually, SkillsDB surfaces key workforce metrics directly within the platform — from individual skill grades to organization-wide training completion. Analytics in SkillsDB are organized across four primary areas: Skills Matrix Analytics , Assessment Completion Reports , Team Training Analytics , and Trainer Metrics . Each area targets a different dimension of workforce capability and can be filtered, customized, and exported to Excel. Administrators have access to all analytics areas. Managers can access team-level analytics for their direct reports and organizational hierarchy. Standard employees cannot access team analytics — they see only their own profile data. All analytics data is based on your organization’s configured grading scale and career structure. Skill grades, benchmarks, and performance thresholds are set by your account administrators and may vary from the examples shown in this article. ​ Prerequisites Before accessing analytics, you need: Permission level : Administrator role for full analytics access; Manager role for team-level analytics Setup requirement : At least one career configured in Library > Careers (for Skills Matrix Analytics) Setup requirement : At least one assessment launched (for Assessment Completion Reports) Setup requirement : Library Roles must be enabled in your organization settings for Skills Matrix Analytics to be available ​ Skills Matrix Analytics The Skills Matrix is SkillsDB’s primary analytics tool for understanding skill proficiency across a career or role. It shows every person assigned to a career alongside their grades for each skill in that role, making it easy to spot proficiency gaps, high performers, and training needs at a glance. The Skills Matrix supports six display views, allowing you to switch between tabular data and visual chart formats without leaving the page. Administrators can access the Skills Matrix for any career. Managers cannot access the Skills Matrix analytics unless they also hold an Administrator role. ​ Accessing the Skills Matrix Navigate to Library > Careers Select the career you want to analyze Select Skills Matrix The page title displays as Analytics / [Career Name] . The Skills Matrix table view loads by default. ​ Choosing a display view The Skills Matrix page supports six display views. Select Display in the top-right navigation area to open the view options panel. View Format Description Skills Matrix Table Default view — shows each person’s skill grade for every skill in the career Training Matrix Table Shows training assignment dates and completion status per skill Skills Flag Table Shows which Mentor, Expert, Focus, and Interest flags are applied per skill Skill Radar Chart Radial chart visualizing skill grade distribution across the career Bar Chart Chart Horizontal bar chart comparing average skill grades across skills Learning Chart Bar chart showing training resource statistics for the career Note: The Manager / Employee grade tab toggle is only available in the Skills Matrix table view. Use this toggle to switch between manager-submitted grades and employee self-assessment grades. ​ Filtering Skills Matrix data The Skills Matrix includes filters to narrow data by organizational structure and performance criteria. Its Direct Reports and My Org scope chips can be selected independently. Both selected shows My Org, which includes direct reports. With neither selected, you see all people your permissions allow. Organizational filters (available across all views): People — Filter by individual name Department — Filter by department Division — Filter by division Region — Filter by region Performance filters (available in the Skills Matrix and Bar Chart views via the Display drawer): Filter Shows Meets Target People whose grade equals the career benchmark Exceeds Target People whose grade is above the career benchmark Below Target People whose grade is below the career benchmark Unassigned People who have not received a grade for a skill Skill flag filters (available in the Skills Flag view): Filter by Mentor, Expert, Focus, or Interest flags to see only flagged skills Filters apply immediately and update the table or chart in real time. Combine multiple filters to narrow the data further. Tip: Use the Below Target performance filter to quickly identify skill gaps within a role. Combine it with the Department filter to see which departments are most affected. ​ Exporting Skills Matrix data All Skills Matrix views can be exported to Excel. The export includes all visible rows and columns in the currently selected view. Apply any filters and select the view you want to export Select Export in the top-right navigation area A .xlsx file downloads automatically The exported filename follows the format: [Career Name]_[View Type]_[Grade Tab]_[YYYY-MM-DD].xlsx ​ Assessment Completion Reports Assessment Completion Reports show the real-time status of a manager or employee assessment across your organization. Use these reports to track who has completed an assessment, who is still in progress, and who has not yet started — without contacting each manager individually. Assessment reports are available for both manager assessments and employee assessments. Administrators can view reports for all assessments. Managers can view completion reports for assessments within their team scope. ​ Accessing an assessment report Navigate to Company > Assessments Select the assessment you want to report on Select View Status Report while the asse --- ## Assessment Population URL: https://help.skillsdb.com/core-concepts/assessment-population Administrators can target an assessment to everyone eligible or to selected organizational groups. The Population step shows the eligible-recipient count and exclusions together. ​ Choosing your audience The Population step controls who receives an assessment. You can select All People to include everyone eligible in your organization, or Select Groups to narrow the audience using your company’s organizational structure. The fields are grouped under Organization , Location , Work Schedule , and People . Only configured dimensions appear. Each field supports multiple selections and shows the selected names. The number of groups picked appears beneath the fields. This counts selections, not people: two selected departments can contain many recipients. The recipient count below the filters reflects assessment eligibility. People need an assigned career skill under a career that enables both proficiency and assessments. Someone can match your organizational filters and still be excluded because they have no assessable skills. The same callout explains how many people have no assigned skills and how many are excluded by career settings. Membership stays dynamic while an assessment is live. People who newly match the audience and eligibility requirements are added automatically. Changing the Population step while creating or editing an assessment uses the same organizational fields; existing selections appear when you edit. With Select Groups active and nothing selected, the count previews everyone eligible. Select at least one group before continuing in this mode. Switching to All People hides the group fields without erasing your draft selections. Switch back to Select Groups to continue refining those selections. ​ Before you begin You need permission to create or edit company assessments. People and organizational groups must be configured in SkillsDB. Career settings must enable proficiency and assessments for the skills you want assessed. ​ Set the population 1 Open the Population step Navigate to Company > Assessments and start a new assessment. Complete Selection and Basic Info , then select Continue to reach Population . When editing an assessment, open its Population step to review the saved audience. 2 Choose everyone or selected groups Select All People for everyone eligible. For a targeted audience, select Select Groups , open a field, and check the groups to include. Available dimensions include Business Unit, Division, Department, Team, Country, Region, City, Site / Office, Shift, and People Type. Only your company’s configured options appear. 3 Review the count and exclusions Review the eligible-recipient count immediately below the group fields. Wait for Calculating recipients… to finish after changing filters. If the count is unavailable, select Retry count ; your selections remain. If no eligible recipients match, review the filters and career exclusions before proceeding. 4 Continue building Once the audience is correct, select Save & Continue . Continue configuring the assessment in the Builder. Saving the population does not replace the remaining assessment configuration steps. ​ Common questions Why are some people in my selected groups excluded? The groups-picked number counts your selections. The recipient count counts eligible people. Review the exclusion explanation for people without assigned skills or with proficiency or assessments disabled in their career settings. Does a loading or failed count mean there are no recipients? No. A pending count is still being calculated. A failed count is unavailable. Only a completed count can report that no eligible recipients match. Select Retry count if the request fails. Why do different audience pickers have different fields? Each feature supports its own targeting dimensions. Assessments support People Type. Surveys and saved-page audiences do not offer People Type targeting. The available organizational options also depend on your company’s configuration. ​ Related articles Careers Understand the careers and skills used to determine assessment eligibility. Manager Assessments Grade and review assessments for your team. ​ Need help? Contact your organization’s SkillsDB administrator or SkillsDB Support . --- ## Career Pathways URL: https://help.skillsdb.com/core-concepts/career-pathways Quick Summary: Career Pathways in SkillsDB let administrators define structured career progressions — complete with levels, skill requirements, and training settings — so employees and managers can track growth and identify skill gaps. ​ Overview A Career Pathway (called a Career in SkillsDB) is a structured definition of a role or job function within your organization. Each career maps out the skills an employee needs, how those skills are organized into sections, and the progression levels a person can move through — for example, from Junior to Senior. Career Pathways serve as the foundation for talent development in SkillsDB. When an employee is assigned to a career, SkillsDB uses the career’s structure to drive proficiency tracking, training requirements, and self-assessments. Managers and administrators can see each person’s progress against the career benchmark, identify skill gaps, and plan development accordingly. Career Pathways are configured and managed by administrators. Managers can assign employees to careers and view their progress. Employees can view their assigned career overview through their personal dashboard. ​ Understanding Career Pathway structure A Career Pathway in SkillsDB is made up of four building blocks: Component Description Example Career The top-level job role or function ”Software Engineer”, “Product Manager” Level Progression steps within the career ”Junior”, “Mid-Level”, “Senior” Section A grouping of related skills within the career ”Backend Development”, “Communication” Skill An individual competency within a section ”Python”, “REST API Design”, “Code Review” Careers can also belong to a Career Type — an optional category that helps organize careers across your organization (for example, “Job Role” vs. “Specialty Path”). Note: Each career is independent. A skill can appear in multiple careers, and each career defines its own training requirements and proficiency benchmarks for that skill independently. ​ Prerequisites Before you create and configure Career Pathways, you need: Permission level: Administrator role in SkillsDB Setup requirement: Skills must already exist in your Skills Library before they can be added to a career Access: Navigate to Library > Careers from the left sidebar Managers can assign employees to existing careers but cannot create or configure careers. Standard users (employees) can view their assigned career overview but cannot modify career structure or settings. ​ Creating a Career Administrators create careers from the Careers Library. Each new career starts with a name and optional icon and type, and is then configured with levels, sections, and skills. Navigate to Library > Careers from the left sidebar. Select Create Career in the top-right area of the page. In the Add Job Role modal, enter a Career Name (required). Optionally, select a Career Type from the dropdown. Optionally, select an Icon to visually represent the career. Select Create . The career is created and opens in the career details panel, where you can configure levels, sections, skills, and settings. Tip: Use Career Types to organize large libraries of careers. For example, separate “Core Job Roles” from “Specialty Paths” or “Development Programs” so admins can filter and manage them more easily. ​ Configuring Career Settings Each career has configurable settings that control how proficiency, training, assessments, and dashboards behave for employees assigned to that career. Access career settings from the career details panel by selecting Settings . ​ Proficiency grading Proficiency grading enables skill-level scoring within the career. When proficiency grading is enabled, grade columns appear in the skills matrix and employees’ proficiency scores are included in search and analytics results. When proficiency grading is disabled, grade columns are hidden and grading data is excluded from all search results and analytics reports. Important: Disabling proficiency grading on an existing career will hide all proficiency data across the career. The underlying data is preserved and reappears if proficiency grading is re-enabled. ​ Training dates Training dates enables training approvals and makes the career’s skills visible in the training matrix. When training dates are enabled, employees can request training approval for skills within the career, and those skills appear in Team > Training > Training Matrix . When training dates are enabled, you can also set a Training Timeline — the expected time for an employee to complete training for all skills in the career. The timeline is configurable in days, months, and years. ​ Assessments Assessments include the career’s skills in manager and self-assessments. This setting is only available when proficiency grading is enabled. If proficiency grading is disabled, assessments are automatically disabled as well. ​ User dashboard The User Dashboard gives employees a personal career overview at Profile > Career > Overview . When enabled, the dashboard displays career-specific metrics and progress indicators. You can choose which components appear on the employee’s dashboard: Career Description — displays the career’s description Training Dates Summary — shows training completion progress Proficiency Summary — shows overall proficiency across career skills Pinned Pages — shows pages pinned to the career ​ Managing Career Levels Career levels define the progression stages within a career. Levels are ordered and represent advancement — for example, Level 1 = “Junior”, Level 2 = “Mid-Level”, Level 3 = “Senior”. Administrators manage levels from the career details panel. To add a level: Navigate to Library > Careers and select the career. In the career details panel, open the levels management section. Select Add Level . Enter a Level Title (for example, Junior , Senior , Principal ). Select Save . To reorder levels, drag and drop them into the desired position. The sort order determines how levels appear to managers and emplo --- ## Careers URL: https://help.skillsdb.com/core-concepts/careers Quick Summary: A career in SkillsDB is the top-level container that defines the skills, sections, training requirements, and benchmarks for a job role. Everything in SkillsDB — assessments, training, analytics, and user dashboards — is organized through careers. ​ Overview In SkillsDB, a career represents a job role or functional area within your organization. Careers are the foundational building block of the platform: they define which skills are relevant to a position, how those skills are grouped, what training is required, and how proficiency is measured. When you assign a person to a career, they inherit that career’s full skill profile — every skill, section, benchmark, and training requirement. This means that when an employee completes an assessment, requests training, or views their skills profile, they are working within the structure you have defined for their career. Careers are organized hierarchically. A career contains sections , and each section contains skills . Sections are used to group related skills into logical categories (for example, a Software Engineering career might have sections for Backend, Frontend, and Architecture). You can also define levels within a career (for example, Junior, Mid, Senior) that apply different benchmark expectations to the same skill set. Careers integrate directly with assessments, the Training Matrix, the Skills Matrix, analytics, and the user-facing Career Overview dashboard. The settings you configure per career control what features are active for people assigned to that career. Note: The Careers library is enabled or disabled per organization via a platform setting. If you do not see Library > Careers in your sidebar, contact your SkillsDB account manager to enable this feature. ​ Prerequisites Before creating or managing careers, ensure you have: Permission level: Administrator role in SkillsDB Feature enabled: Careers library enabled for your organization Access required: Navigate to Library > Careers in the left sidebar ​ Understanding Career Structure Every career in SkillsDB follows the same three-level hierarchy: Level Purpose Example Career The top-level container representing a job role or functional area Software Engineer, Operations Manager, Customer Success Rep Section A logical grouping of related skills within the career Backend Development, Leadership, Client Communication Skill An individual competency that can be graded, assessed, and trained Python, Stakeholder Management, CRM Systems Skills do not need to be organized into sections — you can add skills directly to a career without creating sections first. However, sections help users navigate large skill sets and allow you to attach training resources at the section level. Careers also support levels , which represent seniority or expertise tiers within the same role. When levels are defined, each skill in the career can carry level-specific benchmark expectations (for example, a Junior Software Engineer is expected to reach grade 2 in Python, while a Senior is benchmarked at grade 4). Levels allow you to maintain a single career structure that scales across your organization’s seniority framework. ​ Navigating to the Careers Library To access the careers library: Select Library in the left sidebar navigation. Select Careers . The page title reads Library > Careers and displays a table of all careers in your organization. ​ Understanding the careers table The careers table includes the following columns: Column Description Career The career name. Sortable and filterable. Select a row to open the career detail page. Type The career type (for example, “Job Role”). Defaults to “Job Role” if no type is assigned. Labels Tags applied to the career for filtering and grouping. Up to two labels are displayed inline; hover to see all. People Assigned The count of people currently assigned to this career. Sortable. Settings Four icons showing the enabled/disabled status of Proficiency Grading, Training Dates, Assessments, and User Dashboard. Green checkmarks indicate enabled; red indicators mean disabled. Hover each icon for the setting name. Actions Icon buttons for View Analytics, Settings, Assign Users, Delete, and Edit. Actions are only visible to administrators. ​ Searching and filtering A search input in the top right of the page filters careers by name in real time. Type any part of a career name to narrow the results. The table also supports column-level filtering: select the filter icon on the Career column header to apply additional text filters. ​ Creating a Career Administrators can create a new career from the careers library page. Navigate to Library > Careers . Select Create Career in the top navbar. In the Create Career dialog, complete the following fields: Field Required Description Career Name Yes A unique, descriptive name for the career (for example, “Data Analyst” or “Field Operations Technician”) Icon No An emoji or icon to visually represent the career in the UI Career Type No A category label for the career (for example, “Job Role”, “Department”, “Band”). Defaults to “Job Role” if available. Select Save . When the career is created successfully, a confirmation toast appears and the table scrolls to highlight the new career row. Tip: Enter a unique and descriptive name that matches how your organization refers to the role. The career name appears throughout SkillsDB wherever users see their assigned role — in their Skills Profile, on assessments, and in the Career Overview dashboard. ​ Editing and Deleting a Career ​ Editing a career To rename a career or change its icon or type: Navigate to Library > Careers . In the row for the career you want to edit, select the Edit icon (pencil icon) in the Actions column. In the Edit Career dialog, update the Career Name , Icon , or Career Type as needed. Select Save . ​ Deleting a career To delete a career: Navigate to Library > Careers . In the row for the career, select the Delete icon (trash icon) in the A --- ## Competency Frameworks URL: https://help.skillsdb.com/core-concepts/competency-frameworks Quick Summary: Competency frameworks in SkillsDB let admins define job roles with required skills, proficiency benchmarks, and career progression levels. Once built, people are assigned to roles so skill gaps and training needs can be tracked automatically. ​ Overview A competency framework defines what skills, knowledge, and proficiency levels are expected for a given job role within your organization. In SkillsDB, competency frameworks are built around Careers — structured job roles that combine required skills, proficiency benchmarks, and optional career progression levels. When a person is assigned to a Career, SkillsDB automatically compares their current skill grades against the role’s benchmarks. This produces a real-time view of skill gaps, training completion status, and overall readiness — without any manual calculation. Competency frameworks in SkillsDB serve as the foundation for skills assessments, training tracking, and workforce analytics. They connect your organization’s role definitions directly to individual skill profiles, creating a single source of truth for workforce competency data. Only Company Administrators can create and manage competency frameworks. Once built, the framework drives visibility for managers and employees — surfacing relevant skill gaps, training assignments, and career dashboards within each person’s profile. ​ Prerequisites Before you build a competency framework, you need: Permission level: Company Administrator role Feature availability: The Competency Framework module must be enabled for your organization. Contact your account manager if the Careers option is not visible in the sidebar. Access path: Navigate to Library > Careers from the left sidebar ​ Understanding Competency Frameworks in SkillsDB Competency frameworks in SkillsDB are built from four core components that work together: Component Purpose Example Career The job role itself — the top-level container ”Software Engineer”, “Nurse Clinician” Skills Specific competencies required for the role, each with a proficiency benchmark ”Python” with a benchmark of “Proficient” Sections Logical groupings of skills within a role ”Technical Skills”, “Leadership”, “Safety” Levels Career progression tiers with level-specific benchmarks ”Junior”, “Senior”, “Lead” You can build a framework incrementally — create the Career first, then add skills, organize them into sections, and define levels at your own pace. Each component is optional except for the Career itself. Note: The proficiency benchmarks (e.g., grades like 1–5 or letter grades) are determined by your organization’s grading scale, which is configured separately by your account admin. Benchmarks you set in a Career reference that grading scale. ​ Creating a Career Creating a Career is the first step in building a competency framework. Each Career represents one job role or position type in your organization. Navigate to Library > Careers from the left sidebar Select Create Career in the top-right navbar In the Create Career modal, enter a Career Name — this is required and should be unique and descriptive (e.g., Software Engineer , Field Technician ) Optionally select an icon to visually identify the career Select a Career Type from the dropdown to categorize this role (defaults to “Job Role”). Career types help group and filter careers across your organization Select Save The new Career appears in the Careers table and is immediately available for skills, levels, and people assignments. Select the Career name to open its detail page and begin building the framework. Tip: Use Career Types consistently to categorize your roles (e.g., “Job Role”, “Functional Area”, “Department”). You can manage available types using the Manage Types button in the Careers navbar. ​ Adding Skills to a Career Skills are the core of a competency framework. Each skill attached to a Career includes an optional proficiency benchmark — the expected grade an employee should reach for that role. ​ Adding an existing skill Navigate to Library > Careers and select the Career you want to edit In the Skills section, select Add Skill In the Add Skills modal, use the search box to find an existing skill from your organization’s skill library Select the skill from the results Optionally set a Benchmark — the proficiency level expected for this role (e.g., “Proficient”, “Expert”). If no benchmark is set, the skill is tracked but not compared against a target Select Save The skill is added to the Career and appears in the Skills section. If you have defined Sections, you can assign the skill to a section at this step or move it later. ​ Creating a new skill directly If the skill you need does not yet exist in your library, you can create it directly from the Add Skills modal. In the Add Skills modal, enter the new skill name in the search box When no existing skill matches, a form appears to define the new skill Enter the Skill name (required) — for example, Skills Management Optionally enter a Description Optionally set a Benchmark Select Save The new skill is created in your organization’s library and immediately added to the Career. ​ Organizing Skills into Sections Sections let you group skills within a Career into logical categories. This makes large competency frameworks easier to read and navigate — both for admins and employees. ​ Adding a section On the Career detail page, select Add Section in the Skills area In the Add Section modal, enter a Section Name (required) — for example, Technical Skills or Core Competencies Optionally enter a Section Description Select Save The section appears in the Career’s skill list. Existing skills not yet in a section can be moved into it, and new skills can be added directly to any section using that section’s own Add Skill button. Note: The first section you create groups all existing unsectioned skills into it automatically. Additional sections start empty and require skills to be added directly. ​ Editing or removing a section --- ## Files URL: https://help.skillsdb.com/core-concepts/documents Quick Summary: Files in SkillsDB lets employees upload and store files directly on their profile. As an admin, you control the document types used to categorize those files and determine how documents are organized across your organization. ​ Overview This feature gives employees a place to store and organize files directly within SkillsDB — no external file-sharing service required. Employees can upload supporting materials such as certificates, licenses, resumes, training records, and any other relevant documentation to their personal profile. Files in SkillsDB serve three primary purposes: Providing documentation for the certification workflow: when an employee submits certification details, they attach supporting documents as evidence of completion. Support training records in a similar way — employees attach proof of training as part of a training record submission. Employees can upload general-purpose files to their profile for reference, accessible to managers who oversee them. As an administrator, your primary responsibility in the files feature is configuring document types — the categories used to classify uploaded files. Document types appear as a required field during every file upload, keeping your organization’s documents organized and filterable. SkillsDB ships with a default set of system document types, and you can add as many custom types as your organization needs. Files are stored securely in cloud storage and are accessible only to the employee who uploaded them, their managers, and administrators with the appropriate permissions. ​ Prerequisites Before managing Documents settings, you need: Permission level: Administrator role in SkillsDB Access requirement: Navigate to Settings > Files to manage document types Employees can upload documents without any special permissions beyond a standard SkillsDB account. Managers can view documents uploaded by their direct reports. ​ Understanding File Types Filea types are administrator-configured categories that classify uploaded files. Every file uploaded to SkillsDB must be assigned a document type at the time of upload. File types appear as a dropdown in the upload modal and as a filterable column in the files table. SkillsDB includes system document types that cannot be deleted. System types are used internally by the platform to categorize certification attachments, training record attachments, and general files. You can supplement the system types with custom types that reflect your organization’s specific filing conventions. Type Description Can be deleted? System file types Built-in types used by SkillsDB for certifications and training records No Custom file types Organization-specific types created by administrators Yes Note: If you delete a custom file type that has files assigned to it, SkillsDB automatically reassigns those files to the default type “Other.” No files are deleted when a document type is removed. ​ Configuring File Types Administrators manage file types from the Settings page. File types you create here become immediately available as options during file upload across your entire organization. ​ Adding a new document type Navigate to Settings from the left sidebar Locate the Files section and select Configure In the Manage File Types dialog, select Add Type Enter a file type name (required) Select Save The new document type appears in the list and becomes immediately available for employees to select when uploading files. ​ Editing a file type Administrators can rename any custom document type at any time. System document types are read-only and cannot be renamed. Navigate to Company > Settings , then select Configure beside Files In the Manage File Types dialog, select the name field of the type you want to edit Update the Type Name Select Save All existing files assigned to that type automatically reflect the updated name — no reassignment is needed. ​ Reordering file types The order of document types in the drawer determines the order they appear in the upload dropdown for employees. Navigate to Company > Settings , then select Configure beside Files In the Manage File Types dialog, drag the handle icon on the left of any type to reposition it The order is saved immediately. New or renamed types still need Save . ​ Deleting a custom file type You can delete any custom file type. System file types cannot be deleted. Navigate to Company > Settings , then select Configure beside Files Locate the custom file type you want to remove Select its trash icon Review the confirmation message, which shows how many files will be reassigned to “Other” Select Delete in the confirmation beside the row Important: Deleting a file type does not delete the files assigned to it. Those files are automatically reassigned to the default type “Other.” This action cannot be undone. ​ How Employees Upload Files Understanding the employee upload experience helps you configure document types that are meaningful and easy to select. Employees access their files from Files in the left sidebar, which opens the My Files page. ​ Upload process Employees upload files by selecting Upload File in the top right of the My Files page. The upload modal accepts up to 5 files per upload session. For each file, employees must: Select or drag in the file from their device Choose a File Type from the dropdown (required) Select Upload Files to complete the upload Accepted file types: .jpg , .jpeg , .png , .pdf , .docx , .xlsx , .txt , .csv File size limit: 10 MB per file Maximum files per upload: 5 files If an employee tries to upload a file that exceeds 10 MB or is not an accepted file type, SkillsDB displays an error message and prevents the upload from completing. ​ Viewing and Filtering Files Employees see all their uploaded files on the My Files page. Managers can view documents uploaded by their direct reports when viewing a team member’s profile. ​ My Files table columns Column Description File The file name, displayed as a clickable li --- ## Email Notifications URL: https://help.skillsdb.com/core-concepts/email-notifications Quick Summary: SkillsDB automatically sends email notifications when something happens in the product that needs a person’s attention — a certification is about to expire, an assessment has been assigned, a training request needs approval, a survey has been launched. Every email is paired with an in-app inbox entry so recipients have both a prompt and a place to act. ​ Overview SkillsDB sends transactional email notifications when meaningful events happen to a user — an assessment is assigned, a certification is submitted for approval, training is nearing expiration, a survey has been launched. Notifications are designed to prompt action without creating email overload: each notification is tied to a specific event and, wherever possible, mirrors an item that also appears in the recipient’s Inbox . This page is a reference for the full set of notification emails SkillsDB sends, what triggers each one, and who receives it. Administrators can use this reference to set expectations during rollouts, troubleshoot missing emails, and understand the sequence of notifications in flows like assessment cycles or certification renewals. Note: Customer-configurable email content — custom subject lines, custom bodies, and customer.io-based delivery — is on the roadmap. Today, SkillsDB sends templated transactional emails. When custom email notices ship, this page will cover how to override the defaults. ​ How SkillsDB Emails Work SkillsDB emails share a consistent structure: Sender. Emails come from the SkillsDB no-reply address, branded with your organization’s name where applicable. Subject line. Descriptive and action-oriented (for example, “You’ve been assigned a self-assessment”). Body. A short explanation of what happened, who it affects, and what to do next. Call-to-action link. Most emails include a direct link back into SkillsDB — for example, to the assessment, certification, or approval that triggered the notification. Context. Emails include the employee name, assessment name, due date, certification name, or other context so the recipient can act without needing to search the product. Most notifications are paired with a matching entry in the recipient’s Inbox , so if an email is missed, the action remains visible in-app. ​ Notifications by Category ​ Assessments Assessment emails coordinate the lifecycle of self-assessments and manager assessments — from assignment, through reminders, to completion. Email Trigger Recipient Self-assessment assigned Admin launches an assessment cycle that includes the user The employee being assessed Manager assessment assigned Admin launches an assessment cycle where the user is the manager The manager assessing one or more direct reports Self-assessment nudge Admin sends a reminder on an open cycle, or the due date approaches The employee with an incomplete self-assessment Manager assessment nudge Admin sends a reminder on an open cycle, or the due date approaches The manager with incomplete assessments Self-assessment completion (notify manager) The employee completes their self-assessment The employee’s direct manager Manager assessment completion (notify employee) The manager completes an assessment of the employee The employee who was assessed Nudge emails include the number of outstanding assessments and a direct link back to the assessment page. ​ Careers, Skills, and Sections Emails that fire when an admin or manager changes what’s assigned to a person. Email Trigger Recipient Career (role) assigned An admin or manager assigns a career to the employee The employee Section (group) assigned An admin or manager assigns a section to the employee The employee Skill assigned An admin or manager assigns an individual skill to the employee The employee Skill graded by employee (notify manager) The employee saves a new self-grade for a skill The employee’s direct manager These notifications help employees understand what they are now expected to learn or demonstrate, and keep managers informed of in-flight self-assessments between formal cycles. ​ Certifications Certification emails run the full lifecycle: assignment → submission → review → expiration. Email Trigger Recipient Certification assigned An admin or manager assigns a certification to the employee The employee Certification submitted The employee submits a certification for approval The employee’s manager Certification approved A manager or admin approves a submitted certification The employee Certification rejected A manager or admin rejects a submitted certification The employee Certification expiring soon (employee) The certification is within the 30-day expiration window The employee holding the certification Certification expiring soon (manager) The certification is within the 30-day expiration window The employee’s manager Certification expired (employee) The certification reaches its expiration date The employee Certification expired (manager) The certification reaches its expiration date The employee’s manager Expiration warnings are sent on a recurring schedule so nothing lapses silently. See Training Expirations for the full renewal flow. ​ Training and Learning Email Trigger Recipient Learning resource assigned An admin, manager, or the employee adds a resource to the employee’s learning plan The employee Learning assignment updated One or more items in the employee’s assigned learning are changed in bulk The employee Suggested training approved An admin approves a training suggestion submitted by an employee The employee who submitted the suggestion See Building a Learning Plan for how the learning plan itself works, and Training Approvals for the approval workflow. ​ Surveys Email Trigger Recipient Survey assignment An admin launches a survey that targets the user The recipient of the survey Survey nudge An admin sends a reminder on an open survey Users with incomplete survey responses Survey due soon The survey is within the automated reminder window Users with incomplete survey re --- ## Glossary URL: https://help.skillsdb.com/core-concepts/glossary SkillsDB uses a specific set of terms to describe its features and data model. Some terms are standard across the talent development industry; others are SkillsDB-specific names for common HR and learning concepts. This reference covers both, so you can navigate the product confidently regardless of your background. A ​ Analytics and Reporting The set of dashboards, matrices, and exports that surface skill and training data across an organization. SkillsDB analytics includes the Skills Matrix, Training Matrix, Flag Matrix, assessment scorecards, and trainer performance metrics, all filterable by career, department, team, or individual. Administrators and managers use analytics to identify skill gaps, track certification coverage, and make data-driven workforce decisions. ​ Assessment A structured evaluation cycle in which employees are asked to grade their own skill proficiency and managers review and grade their direct reports. Assessments are created by administrators, assigned to specific people or job roles, and tracked through completion statuses for both the employee and the manager. Assessment results feed directly into each person’s Skills Profile and surface in the Skills Matrix. ​ Batch Grading A high-efficiency mode for managers to complete assessments across multiple people or skills in a single session without navigating away from a single page. Batch grading supports two orientations: grading all people for one skill at a time (by skill), or grading all skills for one person at a time (by person). It is designed for managers with large teams who need to complete many assessment reviews quickly. ​ Benchmark The expected proficiency level for a specific skill within a specific Career and level. Benchmarks are set by administrators and serve as the target grade that employees in that role are expected to reach. When an employee’s actual grade falls below their benchmark, SkillsDB identifies that as a Skill Gap. C ​ Career The top-level organizational unit for skills in SkillsDB, equivalent to a job role, position, competency group, or custom classification like “Success Profile” depending on how your organization has configured the system. Each Career contains Sections, which group related Skills, and can have multiple Levels representing seniority tiers. Employees are assigned to one or more Careers, which determines which skills appear in their assessments, Skills Profile, and learning recommendations. ​ Career Overview A read-only analytics view that shows how an entire workforce performs across all levels of a specific Career. Administrators and managers use the Career Overview to see aggregate skill grades, benchmark comparisons, and flag distributions across everyone assigned to that Career. It supports planning decisions like identifying which levels have the greatest skill gaps or where expertise is concentrated. ​ Career Pathway The configured progression route between Careers, indicating which roles an employee might move into from their current Career. Career Pathways help employees and managers understand potential advancement directions and identify the skills needed to qualify for a target role. Administrators define the available pathways in the career library. ​ Career Settings Per-Career configuration options that control how the Career behaves in assessments and Skills Profiles. The two primary settings are Proficiency (whether skill grade levels are shown and evaluated for this Career) and Training Dates (whether training completion dates are the primary measure for skills in this Career rather than proficiency grades). These settings allow organizations to configure SkillsDB differently for roles that measure competency differently — for example, a technical role using grades versus a compliance role using training records. ​ Certification A professional credential, license, or qualification that an employee holds or is expected to obtain. In SkillsDB, certifications are assigned to employees by managers or administrators, tracked with issued and expiration dates, and supported by uploaded documentation. Certifications move through an approval workflow: the employee submits their details, and a manager or administrator approves or denies the submission. ​ Certification Type A category used to classify certifications within the SkillsDB library, such as “AWS”, “Project Management”, or “Safety”. Certification Types allow administrators to organize the certification library and help managers and employees filter certifications by category. Each certification in the library belongs to one Certification Type. ​ Competency Framework The overall architecture of skills, sections, and careers that defines what proficiency looks like across an organization. A competency framework in SkillsDB is built by administrators through the Library and comprises the careers (job roles), the sections within them, the skills assigned to each section, and the benchmarks set for each skill by level. Organizations often align their SkillsDB competency framework with an existing HR or L&D framework such as a SFIA, SHRM, or a custom internal model. ​ Custom Benchmark A manager-level override that replaces the standard role benchmark for a specific employee’s skill with a personalized target grade. Custom benchmarks are useful when an employee’s development path or responsibilities differ from the default expectations set for their Career level. When a custom benchmark is set, it takes precedence over the role-wide benchmark for that individual in the Skills Matrix and Skill Gap calculations. D ​ Department An organizational attribute assigned to employees that identifies their functional area within the company, such as Engineering, Operations, or Finance. Departments are used to filter people in reports, analytics, and search results, and can control access scope for managers with department-level visibility. Administrators configure the department list in Organization Settings. ​ Di --- ## Import/Export URL: https://help.skillsdb.com/core-concepts/import-export Quick Summary: Administrators can bulk-load employee records, certification histories, and career assignments into SkillsDB using CSV or Excel files. The Import page provides downloadable templates, real-time validation, and a full Activity Log for auditing and troubleshooting. ​ Overview The Import/Export feature allows SkillsDB administrators to load large volumes of data into the platform without manual entry. Instead of adding employees, certifications, or career assignments one record at a time, admins can prepare a spreadsheet and upload it in bulk. SkillsDB supports multiple import types, accessible via tabs on the Import page: Skills , Careers , Training , Certifications (certification library), Employee Certifications (approved records), People (employees and org structure), and People Flags Import . Each import type includes a downloadable template, field-level validation, and a post-import results summary that lists exactly which records succeeded and which failed — so you can correct and resubmit only the rows that need attention. The Import page is accessible to administrators only. An Activity Log within the Import page retains a full history of every import operation, including the original file, the importing user, timestamps, and a breakdown of any errors encountered. Note: The Import feature must be enabled for your organization. If you do not see Import in your navigation, contact your SkillsDB account manager. ​ Prerequisites Before running any import, you need: Permission level: Administrator role File format: CSV, XLS, or XLSX files only File size: Maximum 5 MB per import file Access: Navigate to Import from the left sidebar ​ Importing People (Employees) Use the People import to add new employees, update existing employee records, or assign managers in bulk. SkillsDB identifies each employee by their email address — new email addresses create new records, and existing email addresses update existing records. ​ Prepare your file Navigate to Import in the left sidebar. Select the People Import tab. Select Download template to get the SkillsDB_People_Import_Template.csv file. Open the template and populate your data using the columns below. Column Required Notes FirstName Yes Employee’s first name LastName Yes Employee’s last name EmailAddress Yes Unique identifier; must not be duplicated within the file ManagersEmail No Must match an existing employee’s email in SkillsDB JobTitle No Auto-created if it does not already exist Department No Auto-created if it does not already exist Level No Auto-created if it does not already exist IsAdmin No Enter Y or N ; blank preserves existing status for current employees and defaults to non-admin for new employees IsActive No Enter Y or N ; blank preserves existing status for current employees and defaults to active for new employees YourPersonId , BusinessUnit , Division , Country , Region , City , State , Site , Building , Team , Shift No Optional organizational fields for your records; org-structure values (such as Site and Building ) are auto-created if they do not already exist Save your completed file as CSV, XLS, or XLSX. Important: Each email address must appear only once in the file. Rows with duplicate email addresses fail validation and are listed in the results panel. Correct and reimport only the failed rows — successful rows are already processed. ​ Upload and run the import Navigate to Import > People Import . Drag and drop your file into the upload zone, or select Add file to browse your computer. Select Import to begin processing. SkillsDB processes the file in three stages: Validating → Processing → Uploading . When processing completes, the results panel displays a count of successes and a breakdown of any failures by error category. ​ Understand people import results If records fail, the results panel groups errors into categories so you know exactly what to fix: Error category Cause Duplicate emails The same email address appears more than once in the file Existing emails The email belongs to a user registered in a different organization Invalid emails The email address is not correctly formatted Missing emails A row has no email address Manager email conflict A user’s ManagersEmail value matches their own EmailAddress Failed creations The record could not be created due to a processing error Failed manager assignments The manager email does not match any existing employee in SkillsDB Fix only the affected rows in your file and reimport. Rows that already succeeded do not need to be re-uploaded. ​ Importing Employee Certifications Use the Employee Certifications import to bulk-assign certification records to employees. All certifications imported this way are automatically set to Approved status and become each employee’s active certification record. Note: Each certification must already exist in your SkillsDB certifications library before you can import it for employees. If a certification has not yet been created, add it to the library first. ​ Find your SkillsDB Certification IDs The certifications import requires a SkillsDB Certification ID for each row. To find these IDs: Navigate to Import in the left sidebar. Select the Employee Certifications tab. Select Export all certifications list . Open the downloaded SkillsDB_Certifications_List.csv to view all available certification IDs and their names. Copy the relevant IDs into your import file. ​ Prepare your file On the Employee Certifications tab, select Download template to get the Employee_Certifications_Import_Template.csv file. Complete the file using the following columns: Column Required Notes EmployeeEmailAddress Yes Must match an existing employee in SkillsDB SkillsDBCertificationID Yes Must match a certification in your library (see above) IDNumber No The employee’s certificate number from the issuing authority IssuedDate No Format: YYYY/MM/DD (e.g., 2025/06/15 ) ExpirationDate No Format: YYYY/MM/DD (e.g., 2027/06/15 ) Save your completed file as --- ## Inbox URL: https://help.skillsdb.com/core-concepts/inbox Quick Summary: The Inbox is your central hub for everything that needs your attention — assessments to complete, certifications and training to approve, skill requests to review, and survey invitations. Items are organized into categories so you can prioritize what matters most. ​ Overview The Inbox consolidates every actionable item in SkillsDB into a single, filterable list. Instead of checking multiple pages for pending assessments, outstanding approvals, or new requests, you open the Inbox and see everything that requires your attention. What appears in your Inbox depends on your role. Employees see their own assessments and survey invitations. Managers also see team assessments and certification or training approvals. Administrators see all of the above plus skill requests, certification requests, and training suggestions submitted by others across the organization. The Inbox is accessible from the left sidebar and displays a badge count showing the total number of unresolved items. This count updates automatically as items are completed, approved, or archived. ​ Inbox Categories Items in the Inbox are grouped into categories. Select a category from the type filter to narrow the list, or select All Types to see everything together. A category appears only if you have items of that type, so the set you see depends on your role. Category What it contains Who sees it Notices Self assessments, manager assessments, and survey invitations All users (assessments depend on assignment; surveys depend on targeting) Verifications Certification approvals, training approvals, and journey approvals submitted by team members Managers, administrators, and scoped approvers Requests Skill requests, certification requests, and training suggestions Administrators only Rejections Requests that were rejected, and approvals that were later cancelled Anyone whose items were rejected or cancelled All Types Combined view of every category Varies by role ​ Notices Notices include items that require you to take action — typically completing an assessment or responding to a survey. Self Assessment — An assessment assigned to you for self-evaluation. Action: Start (new) or Continue (in progress). Manager Assessment — An assessment assigned to you as a manager to evaluate your team. Shows the number of employees assigned (e.g., “16 employees assigned”). Action: Start or Continue . Survey — A survey you have been targeted with. Action: Start or Continue . ​ Verifications Verifications appear when a team member submits a record that requires your review. Certification Verification — A team member submitted a certification for review. Action: Review (opens the certification detail to approve or reject). Training Verification — A team member submitted a training completion record. Action: Review . Journey Approval — A journey step assigned to you requires your approval. Action: Review . ​ Requests Requests are submitted by employees or managers and require administrator action. Skill Request — An employee requested to add a skill to their profile or to the organization’s library. Action: Review (approve, reject, or edit). Certification Request — A request for a certification to be added. Action: Review . Training Suggestion — A training resource suggestion submitted for review. Action: Review . ​ Rejections Rejections collect the terminal outcomes of the review process in one place, so a decision does not get lost in the main feed. Rejected — A pending request or approval that a reviewer declined. Cancelled — An approval that was granted and later revoked. Employees also see their own rejection notifications here, such as Training Rejected and Training Cancelled . ​ Item Statuses Each Inbox item displays a status badge indicating where it stands: Statuses vary by category. Notices (assessments, surveys) use lifecycle statuses; approvals and requests use review statuses. Notices Status Meaning To do Not yet started Due soon Approaching the due date Past due The due date has passed without completion Complete Finished Verifications, Requests, and Rejections Status Meaning Awaiting Approval Submitted and waiting for a reviewer to act Approved Reviewed and accepted Rejected Reviewed and denied Items with a Past due status display a red warning icon next to the due date. ​ Filtering the Inbox ​ Pending, Archived, and All The view dropdown in the breadcrumb bar lets you switch between three views: Pending — Shows only unarchived, active items. This is the default view and displays a count (e.g., “Pending (11)”). Archived — Shows only items you have previously archived. All — Shows both active and archived items together. Archiving removes an item from your default Inbox view without deleting it. You can always find archived items by switching to the Archived view. Note: If the count exceeds 1,000, the badge displays 1k+ rather than an exact number. SkillsDB stops counting at 1,000 so the Inbox stays fast on very large queues. ​ Filter Controls Select the Filter button to narrow your Inbox by: Status — Filter by item status (To Do, Past Due, Awaiting Approval, etc.) Person — Filter by employee name Due Date — Filter by date range (Today, This Week, This Month, or a custom range) Type — Select or deselect specific item types Filters are reflected in the URL, so you can bookmark a filtered view or save it as a favorite using the Save View button. ​ Taking Action on Inbox Items The Action column on each row provides a button to act on the item: Action What it does Start Opens a new assessment or survey that has not been started yet Continue Resumes an assessment or survey that is in progress Review Opens the detail view for an approval or request so you can approve, reject, or edit it After you complete an action, the item’s status updates automatically and it moves out of the active Inbox view. ​ Inbox Badge Count The sidebar badge next to Inbox shows the total count of items requiring attention. This count is the sum of: Inc --- ## Journeys URL: https://help.skillsdb.com/core-concepts/journeys Quick Summary: Journeys let administrators define an ordered sequence of steps a person moves through automatically over time — for example, the path from finishing required training to being promoted into a new career. A person enrolls when they meet the journey’s enrollment condition, then advances through each step in order until the journey is complete. ​ Overview A Journey is an admin-built workflow made of ordered steps . Each person enters a journey when they meet its enrollment condition, then advances through the steps strictly in order — step 2 only becomes active once step 1 is satisfied — until the journey is complete. Journeys solve a real problem: the multi-step processes a person moves through over time, such as the path from completing required training to a promotion, are usually run manually across training records, manager conversations, and career assignments. There is no single place to define the sequence, watch who is in progress, or audit what happened. Journeys give you that single place. The most common use is promotion automation: when an employee completes all required training for a target career, a journey can route an approval to their manager, request a sign-off from a specific approver, automatically assign a new career or career level, and notify stakeholders — all without manual hand-offs. Only administrators can see and manage journeys. Employees are silent participants: they are enrolled, progressed, and assigned automatically, with no journey-facing screens. The one exception is approvals — a manager or designated approver receives an email and an inbox item linking to a single Activity Page where they action their approval, even though they cannot otherwise see the Company section. Note: The Journeys feature must be enabled for your SkillsDB account. Contact your account manager if you do not see Journeys in the Company sidebar menu. ​ Prerequisites Before you create a journey, you need: Permission level : Administrator or Global Administrator role Target career : At least one career (job role) with required training defined, to use as the enrollment condition Access requirement : Company > Journeys in the left navigation ​ Understanding journey states A journey is always in one of three states. The state determines which actions are available and whether new people can enroll. State Meaning Available actions Draft Being built; not yet live. No one can enroll. Edit, Activate, Delete Activated Live. Eligible people enroll and advance. Backfill, Deactivate Inactive Previously activated, now turned off. No new enrollment. Activate You can edit a journey’s steps only while it is in Draft . Activated and Inactive journeys are read-only to preserve the integrity of in-progress enrollments. You can delete a journey only while it is in Draft . An activated journey has people enrolled on it, so it cannot be deleted — retire it with Deactivate instead. Deleting a Draft permanently removes the journey and its steps. ​ The five step types When you add a step, you choose one of five types and give it a name and description. Each type has its own configuration and its own rule for when it is satisfied. Step type Configuration Satisfied when Training Completion A target career The person has 100% of the required training for that career approved. The first step of every journey must be this type and serves as the enrollment condition. Manager Approval None The enrolled person’s direct manager approves from the Activity Page. Custom Approval Fixed Approver (a specific user) or Case-by-Case The fixed approver approves; or, for Case-by-Case, any admin approves or reassigns. Assign Career/Level A target career and optional career level Runs automatically: the career (and level, if set) is added to the person. If they already hold the exact assignment, the step is a no-op and still counts as satisfied. Notification One or more recipient users Runs automatically: a link to the person’s Activity Page is sent to the recipients. The step satisfies immediately after sending. Note: The target career used for the enrollment (first) step may differ from the career granted by a later Assign Career/Level step. For example: complete training for “Senior Technician” → approvals → assign “Lead Technician”. ​ Adding a condition to a step Any step except the enrollment (first) step can carry an optional condition. A condition is evaluated per person at the moment the step would become active. If the condition is not met, the step is marked Skipped and the journey advances to the next step with no one asked to act. If the condition is met, the step runs as normal. You set a condition in the step’s configuration under Only run this step if… . The default is Always run . The one condition available today is Person has a career assigned , which you pair with a specific career. If you select Person has a career assigned and the person does not have that career when they reach the step, the step is skipped and the journey moves on. A step with a condition shows a Conditional badge wherever it appears. Note: A skipped step is terminal — once skipped, it is never re-evaluated. On a person’s Activity Page a skipped step shows a Skipped status and the reason it was skipped, and it counts as done in the “X/Y steps done” progress. Warning: If the career a condition depends on is later deleted, SkillsDB cannot check the condition. The condition then fails open — the step runs for everyone — and an alert appears on the step. Edit the step to choose a career that still exists, or remove the condition. ​ Creating a journey Build a journey in a three-phase wizard — Details , Enrollment , and Build . 1 Open the wizard Navigate to Company > Journeys and select Journey . 2 Enter details On the Details phase, enter a Journey Name (required) and an optional Description . Journeys do not have a due date. Select Continue . 3 Set the enrollment condition On the Enrollment phase, select Set Enrollment Conditi --- ## Proficiency URL: https://help.skillsdb.com/core-concepts/proficiency Quick Summary: Proficiency measures how skilled someone is at a task using a numeric grade. Trained status records whether someone has completed formal training for a skill. These are two independent tracking systems that can be enabled or disabled per career in SkillsDB. ​ Overview SkillsDB tracks two separate dimensions of skill competency: proficiency and trained status . Understanding the difference between these two systems is essential for configuring your organization’s careers correctly and interpreting data across the Skills Matrix, assessments, and reporting. Proficiency measures the quality of a skill — how well someone performs or understands it. Proficiency is expressed as a numeric grade on a configurable scale (for example, 1–5). Each employee has a self-assessed grade, a manager-assigned grade, and a benchmark grade representing the expected level for their role. Trained status records the completion of formal training — whether someone has an approved training record for a skill and the date that training occurred. Trained status answers the question “Has this person completed training for this skill?” It does not indicate how proficient they are. These two systems operate independently. A person can be highly proficient in a skill through on-the-job experience while having no formal training record. Conversely, a person can have completed training for a skill but still be developing toward the expected proficiency level. Administrators can enable or disable each system separately per career. Note: Proficiency grading must be enabled for a career before assessments can be used. Trained status (training dates) can be enabled independently of proficiency. See Enabling or disabling proficiency for a career for details. ​ Understanding Proficiency Grades Proficiency grades represent measured skill competency. SkillsDB tracks three grade values per person per skill: Grade type Description Who sets it Employee grade The employee’s self-assessment of their own proficiency Employee (via self-assessment or direct grading) Manager grade The manager’s assessment of the employee’s proficiency Manager (via manager assessment or inline edit) Benchmark The expected proficiency level for the role Administrator (set at the role/career level) All three grades use the same grading scale configured for your organization. For example, on a 1–5 scale: 1 = Beginner, 2 = Developing, 3 = Proficient, 4 = Advanced, 5 = Expert. Note: Your organization’s grading scale labels and numeric range are configured by an administrator. The examples in this article use a 1–5 scale, but your organization’s scale may differ. See Configuring the grading scale for details. ​ How proficiency grades display Proficiency grades appear as colored grade pills throughout SkillsDB: A green pill indicates the grade meets or exceeds the benchmark for that skill. A red pill indicates the grade is below the benchmark. A gray pill or empty state indicates no grade has been recorded. Grades appear in the Skills Profile, career detail pages, the Skills Matrix, and assessment scorecards. Employees see their own employee grade and their benchmark. Managers see the employee grade, their own manager grade, and the benchmark for each skill. ​ Not Applicable (N/A) status If a skill does not apply to a particular person, the grade can be set to Not Applicable . When a skill is marked N/A: No proficiency grade is required or tracked for that person and skill. The skill is excluded from average grade calculations. The skill does not contribute to skill gap reporting for that individual. Employees can mark skills as N/A during self-assessments. Managers can mark skills as N/A during manager assessments or from the team skills view. ​ Understanding Trained Status Trained status records whether an employee has a formal, approved training record for a skill. It answers the question “Has this person completed training for this skill?” rather than “How skilled are they?” When training dates are enabled for a career, each skill in that career can display: Training date — The date on which training was recorded as completed. Expiration date — If the training has an expiration, the date it expires. Training status — Whether the training is current, expiring soon, or expired. Training records are tracked in the Training Matrix , which gives managers and administrators a consolidated view of who has completed training and whose training is due to expire. ​ Trained status vs. proficiency: key differences Proficiency Trained status What it measures How skilled someone is Whether formal training is complete Format Numeric grade (e.g., 3 out of 5) Date-based record (completed/not completed) Who updates it Employee (self-grade), manager (manager grade) Manager or administrator (training record entry) Expires? No — grades persist until updated Yes — training records can expire and require renewal Shown in Skills Profile, Skills Matrix, assessments Training Matrix, Skills Profile training section Required for assessments? Yes — proficiency must be enabled No — independent of assessments ​ When both systems apply Both proficiency and trained status can be active for the same career simultaneously. In this configuration, each skill shows both a proficiency grade and a training record. This combination is common in industries where formal certification or compliance training is required alongside competency tracking — for example, safety training where both completion of a course (trained) and demonstrated skill level (proficiency) are tracked separately. Tip: Use both proficiency and trained status when your organization needs to distinguish between “someone who attended training” and “someone who has mastered the skill.” Use proficiency alone for skill development tracking. Use trained status alone for compliance or certification tracking. ​ Configuring the Grading Scale The grading scale defines the numeric values and labels used for proficiency grades --- ## Promotion Workflows URL: https://help.skillsdb.com/core-concepts/promotion-workflows Quick Summary: SkillsDB supports promotion decisions by combining career levels, level-specific skill benchmarks, assessment data, and the skills matrix. Admins configure the framework; managers use the resulting data to evaluate readiness and record a promotion by changing an employee’s career level assignment. ​ Overview A promotion workflow in SkillsDB is not a single button — it is a structured approach to career advancement supported by the platform’s career, assessment, and skills data infrastructure, which you can run by hand or automate with Journeys . When configured correctly, SkillsDB gives managers and admins a clear, data-driven view of whether an employee is ready to move to the next level in their career. The foundation is a career with multiple levels. Each level represents a stage in a progression — for example, Level 1 might be Junior, Level 2 Mid-level, and Level 3 Senior. Each skill within a career can carry a different benchmark grade requirement per level, so what it means to be “proficient” increases as the levels advance. When assessments are run, they generate current skill grade data for each employee. The Skills Matrix then allows managers to compare those grades against the benchmarks for the next level, making skill gaps visible and actionable. When an employee is ready to advance, the promotion is recorded by reassigning them to the new level in their career. This article covers how to configure SkillsDB to support promotion decisions and how to manage the promotion process itself. Automate it with Journeys. When you want the approval and the level change to run without manual tracking, build a Journey : it enrolls a person once they complete all approved training for the target career, routes a manager or custom approval by email and Inbox, assigns the new career or level on approval, and notifies stakeholders — in strict step order, with every action logged on the journey’s Activity Page. The manual process below still applies when you want a person to make each call by hand. ​ How Career Levels Work Career levels represent the seniority tiers or stages of advancement within a single career. A career can have one level (no tiered progression) or many levels representing a full career ladder. Levels are ordered and labeled by admins. Common patterns include: Example Configuration Level 1 Level 2 Level 3 Level 4 Seniority tiers Junior Mid-level Senior Principal Numeric tiers L1 L2 L3 L4 Named progression Associate Professional Expert Fellow Each person assigned to a career is also assigned to a specific level. The level appears throughout SkillsDB — on the person’s profile, in the skills matrix, and in career assignment views — giving managers immediate context about where an employee stands in their career progression. Levels are managed per career from Library > Careers > [Career Name] > Manage Levels . ​ Setting Up Level-Specific Skill Benchmarks To make levels meaningful for promotion decisions, each skill in a career can carry a different benchmark grade requirement for each level. This means the system knows that a “Senior” (L3) engineer needs a higher grade in Python than a “Junior” (L1) engineer. Level benchmarks are configured in the career’s skill settings. When benchmarks are set at multiple levels, the skills matrix can show whether an employee meets the benchmark for their current level — and whether they are close to meeting the benchmark for the next level. To configure level-specific benchmarks: Navigate to Library > Careers Select the career you want to configure In the career detail view, open the skills list for a section For each skill, set the benchmark grade for each level using the level benchmark controls Repeat for all skills across all sections in the career When benchmarks exist for multiple levels, managers can use the Skills Matrix filter to view the gap between an employee’s current grades and the requirements for a target level. Note: If your organization uses a grading scale (e.g., 1–5 proficiency levels), the benchmark grades you set should correspond to that scale. Grading scales are configured by admins in Settings > Grading Scale . ​ Enabling Assessments for Career Skills Assessments generate the current grade data that makes promotion readiness visible. Without assessment data, the skills matrix cannot show whether an employee meets a level’s benchmarks. Each career can be individually configured to include its skills in assessments. This setting is found in the Career Settings section of the career detail page. To enable assessments for a career: Navigate to Library > Careers Select the career Scroll to Career Settings Ensure Proficiency Grading is enabled — this makes skill grades visible and used in analytics Ensure Assessments is enabled — this includes the career’s skills in manager and self-assessments Select Save or the relevant update button Important: Assessments require Proficiency Grading to be enabled. If you disable Proficiency Grading for a career, assessments are automatically disabled as well, and grade data is hidden from the skills matrix and analytics. ​ Evaluating Promotion Readiness Once careers have levels, level benchmarks, and assessments enabled, managers and admins can evaluate promotion readiness through the Skills Matrix . ​ Viewing the skills matrix for a career Navigate to Library > Careers > Skills Matrix and select the career to view. The matrix displays: All employees assigned to the career as rows All skills within the career as columns Each employee’s current grade for each skill in the cell Benchmark indicators showing whether the grade meets, exceeds, or falls below the target benchmark Use the level filter in the matrix to compare employees against a specific level’s benchmarks — for example, filtering to “L3 Senior” benchmarks shows you whether current L2 employees are ready to advance. ​ Identifying skill gaps Employees whose current grades fall below the benchmarks for the next lev --- ## Search URL: https://help.skillsdb.com/core-concepts/search Quick Summary: Search lets users find people, training, skills, careers, and certifications across your organization. Admins control which roles have access to search and how much of the organization they can see through granular, role-based permissions. ​ Overview Search is a core navigation tool that enables employees, managers, and admins to explore your organization’s talent, training resources, and skills data. Depending on how permissions are configured, users can search for colleagues by skill, find training courses, browse careers, or locate certification holders — all from a single search interface. Because Search surfaces potentially sensitive organizational data, it is fully permission-gated. Admins configure exactly what each security group can search for and how broadly they can see results. For example, managers might only see people within their own chain of command, while admins have unrestricted access. Search is accessible from the left sidebar and is available to any role that has been granted search access by an admin. ​ How Search Works When users open Search, they can: Search by keyword — Enter any text to search across multiple content types simultaneously Filter by type — Use the type tabs to scope results to People , Training , Skills , Career , or Certifications , or view All results together Apply structured filters — Narrow results by organizational structure (business unit, department, team, location) as well as skill grades, career levels, skill flags, certifications, and document content Toggle match mode — Choose Match All to require every filter to apply, or Match Any to return results that match at least one View recent searches — Previously run searches are stored locally for quick re-use The filters and content types visible to each user depend on the permissions configured for their security group. A user who does not have People Search access will only see training, skill, and career results — not colleagues. ​ Configuring Search Permissions Search permissions are managed from Company > Settings > Search Permission . This page displays a permission matrix with one column per security group and one row per permission type. Each cell can be independently configured. To open Search Permissions: Navigate to Settings from the main menu Select Search Permissions from the settings list The Search Permissions matrix will load, showing all security groups and configurable permission rows ​ Security Groups Permissions are configured independently for each of the four security groups: Security Group Notes Admin Search is always enabled; most permissions are not individually configurable Manager Fully configurable; selecting Chain of Command automatically restricts all filters Employee Fully configurable; supports the Above Grade people search option Full Access People Search Access is locked at Full Access; other filters are configurable ​ Permission Reference ​ Enable Search Controls whether the search feature appears in the sidebar at all for a given role. Enabled (checkbox checked): The Search button appears in the left navigation Disabled (checkbox unchecked): Search is completely hidden from that role Search is always enabled for Admins and cannot be turned off. ​ People Search Access Controls the scope of people a user can find when searching for colleagues. This is the most impactful permission setting. Access Level Behavior No Access People search is disabled; users cannot search for colleagues at all Full Access Users can find any person in the organization that matches the search criteria Chain of Command Users can only find people within their direct reporting hierarchy Above Grade Users can only find people who are graded above a specified minimum grade level when searching by skills Full Access users always have Full Access to people search. This setting cannot be changed for the Full Access security group. When People Search Access is set to No Access , all filter permissions below it are automatically forced to No Access as well, and the default search mode is set to Training. These changes take effect immediately and cannot be overridden individually while People Search is disabled. ​ Minimum to Appear in Results This setting only appears when People Search Access is set to Above Grade for the Employee or Manager role. It defines the minimum skill grade a person must hold to appear in skill-based search results for that role. The Minimum to Appear in Results selector requires at least one grading rubric to be configured in your organization before it can be set. If no grading rubrics exist, configure them first before using the Above Grade access level. ​ Filter Permissions The following filters can each be independently configured per security group. Each accepts one of three values: Access Level Behavior No Access The filter is hidden and unavailable to that role Chain of Command The filter is available but results are scoped to the user’s reporting hierarchy Full Access The filter is available with no scope restriction When People Search Access is set to Chain of Command for a security group, all filter permissions for that group are automatically limited to No Access or Chain of Command only. Full Access is not available for any filter when the people search scope is chain-of-command. Skill Grades Filter Allows users to filter search results by the proficiency grade level of a skill. Useful for finding employees who have achieved a specific grade in a skill. Search Based on Careers Allows users to filter or search by career assignments — finding colleagues who currently hold, or have previously held, a particular career. Career Level Filter Allows users to filter search results by career level (e.g., Entry, Mid, Senior). Skill Flags Filter Allows users to filter search results by flags that have been applied to skills on employee profiles (e.g., Endorsed, Flagged for Review). Survey Response Filter Allows users to filter search results based --- ## Sign in & SSO URL: https://help.skillsdb.com/core-concepts/sign-in-and-sso Quick Summary: SkillsDB supports two sign-in methods — email/password, and Single Sign-On (SSO). Which method is available to you depends on how your organization has configured SkillsDB. ​ Overview SkillsDB is a web-based application accessed through your browser at app.skillsdb.com . To use SkillsDB, you must sign in with a verified account. There are two ways to sign in: Email and password — You sign in with the email address and password associated with your SkillsDB account. Single Sign-On (SSO) — You sign in using your organization’s existing identity provider (such as Okta, Microsoft Azure AD, or Google Workspace). SSO allows you to access SkillsDB with the same credentials you use for other company tools, without a separate SkillsDB password. The sign-in method available to you is determined by your organization’s configuration. If you are unsure which method to use, contact your administrator. SkillsDB accounts are created by administrators. You cannot create your own SkillsDB account — you will receive an invitation from your administrator when your account is ready. ​ Prerequisites Before you can sign in, you need: An active SkillsDB account : Created and activated by your organization’s administrator Your sign-in credentials : Either your SkillsDB email and password, or access to your organization’s SSO provider A supported web browser : A modern browser such as Chrome, Firefox, Safari, or Edge with cookies enabled ​ Signing In with Email and Password Email and password sign-in is available when your organization uses SkillsDB’s built-in authentication. If your organization uses SSO, see Signing In with SSO below. Navigate to app.skillsdb.com — you will be directed to the sign-in page automatically Enter your Email address in the email field Enter your Password in the password field Select the eye icon to toggle password visibility if needed Select Sign in When sign-in is successful, SkillsDB redirects you to your home page. Your session remains active for 24 hours, after which you will need to sign in again. Important: If you see the message “Your account has been deactivated. Please contact your administrator,” your account has been disabled. Contact your SkillsDB administrator to restore access. ​ Resetting Your Password If you have forgotten your password, you can request a reset link by email. The reset link is valid for a single use only. Step 1: Request a reset link Navigate to the sign-in page at app.skillsdb.com Select Forgot Password? below the Sign in button Enter the Email address associated with your SkillsDB account Select Send Reset Link If your email address is recognized, SkillsDB sends a password reset link to your inbox. You are then redirected to the sign-in page. Note: Check your spam or junk folder if the reset email does not arrive within a few minutes. Step 2: Set a new password Open the password reset email in your inbox Select the reset link in the email — the link opens the Reset Password page Enter your new password in the Password field Enter the same password again in the Confirm Password field Select Reset Password When your password is reset successfully, you are signed in automatically and redirected to your home page. Password requirements Your new password must meet the following requirements: Requirement Detail Minimum length 8 characters Uppercase letters At least one (A–Z) Lowercase letters At least one (a–z) Numbers At least one (0–9) Symbols At least two from: `! @ # $ % ^ & * ( ) , . ? ” : < >` Important: SkillsDB checks new passwords against a database of known compromised passwords. If your chosen password has appeared in a public data breach, you will be prompted to choose a different one. ​ Signing In with SSO Single Sign-On (SSO) allows you to sign in to SkillsDB using your organization’s existing credentials — the same username and password you use for tools like email, Okta, or Microsoft 365. SSO must be configured by your organization’s administrator before you can use it. For administrators: Configuring SSO or SCIM for your organization is done in Settings > SSO & SCIM . See Identity & Provisioning for setup, group mapping, and provisioning options. SkillsDB supports SSO via the SAML 2.0 standard and is compatible with identity providers including: Okta Microsoft Azure AD (Microsoft Entra ID) Google Workspace Any other SAML 2.0-compliant identity provider SSO sign-in flow When your organization has SSO enabled, the sign-in experience works as follows: Navigate to app.skillsdb.com You are redirected to your organization’s identity provider (for example, an Okta or Microsoft login page) Enter your organization credentials and complete any required authentication steps your provider requires Your identity provider confirms your identity and redirects you back to SkillsDB SkillsDB signs you in automatically — the Authenticating screen appears briefly while your session is established You do not need a separate SkillsDB password when SSO is enabled. Your access to SkillsDB is controlled entirely by your organization’s identity provider. Note: If you have questions about your SSO credentials or encounter login issues with your identity provider, contact your IT or HR team — they manage the identity provider, not SkillsDB. ​ Your Session and Signing Out Session duration A SkillsDB session lasts for 24 hours by default. After 24 hours of inactivity, your session expires and you will need to sign in again. Your data and settings are never lost when a session expires. If you navigate to SkillsDB after your session has expired, you will be redirected to the sign-in page. After signing in, you are returned to the page you were trying to access. Signing out To sign out of SkillsDB, select your profile icon or name in the top-right corner of the screen and select Sign out . Signing out immediately ends your session and returns you to the sign-in page. Tip: Sign out of SkillsDB when using a shared or public computer to prevent others from ac --- ## Skill Flags URL: https://help.skillsdb.com/core-concepts/skill-flags Quick Summary: Skill Flags are colored labels you and your manager can apply to skills to add context beyond a proficiency grade. Use flags to mark skills as development priorities, signal learning interests, or recognize expertise and mentorship — directly within your Skills Profile or during assessments. ​ Overview Skill Flags are labels applied to skills in SkillsDB to add meaning beyond a proficiency grade. While a grade tells you how skilled someone is in a given area, a flag communicates why that skill matters — whether it is a current development priority, a future aspiration, or a domain where someone is recognized as an authority or coach. Flags can be applied to an individual skill, to an entire section of related skills, or to a whole career. This flexibility allows a single flag to communicate intent across a broad area without having to label each skill one at a time. There are two main categories of skill flags. User-applicable flags — Focus and Interest — can be applied by any employee directly to their own skills. Manager- and admin-applied flags — Expert and Mentor — are applied by a manager or administrator to recognize specific capabilities. Your organization may also have custom flags created by an administrator to reflect company-specific roles or initiatives. Flags are visible to you, your manager, and administrators. They appear alongside your skills in your Skills Profile, during assessment cycles, and in team-level views that managers use to understand the distribution of expertise and development goals across their team. ​ Default Skill Flags SkillsDB includes four default skill flags. Your organization may also have additional custom flags configured by an administrator. Flag Color Who can apply it Purpose Expert Purple Your manager or an admin Recognizes deep expertise in this skill Mentor Green Your manager or an admin Identifies you as a coaching resource for this skill Focus Blue You, your manager, or an admin Marks a skill as an active development priority Interest Yellow You only Signals you want to develop or learn this skill Note: The flags available to you depend on your organization’s configuration. Administrators can enable, disable, or create custom flags. If a flag described here is not visible in your account, it may not be active for your organization. ​ Focus The Focus flag marks a skill as an active development priority for you. Applying Focus to a skill signals to your manager that you are working on improving in that area and want it to be part of your growth conversations. You can apply the Focus flag in two places: During a self-assessment — When grading a skill, select the Focus toggle to mark it as a development priority. This is saved to your profile and persists after the assessment closes. See Self Assessments for instructions. From your Skills Profile — You can apply or remove Focus at any time, independent of any active assessment. To apply the Focus flag from your Skills Profile: Navigate to your Skills Profile by selecting Skills from the left sidebar. Locate the skill you want to flag. Select the flag icon or the flag selector for that skill. Select Focus from the list of available flags. The skill updates immediately to display the yellow Focus badge. Your manager can also apply the Focus flag to skills in your profile. If your manager has set a Focus flag on a skill, only your manager or an administrator can remove it — the flag will appear active on that skill but you will not be able to toggle it off. If you applied Focus yourself, you can remove it at any time by selecting the flag again. ​ Interest The Interest flag indicates that you want to learn or develop a skill, even if it is not currently part of your assigned career path or role requirements. Interest flags help your manager and organization understand where you want to grow beyond your current scope. Unlike the Focus flag, Interest is self-applied only. Your manager cannot set an Interest flag on your behalf, and the Interest flag does not appear during manager assessments — it is solely for capturing your own development intentions. To apply the Interest flag: Navigate to your Skills Profile by selecting Skills from the left sidebar. Locate the skill you want to flag. Select the flag icon or the flag selector for that skill. Select Interest from the list of available flags. You can apply the Interest flag to any skill in SkillsDB — not just skills assigned to your current role or career path. This is by design. Interest flags are intended to capture aspirations that extend beyond your immediate job requirements. To remove an Interest flag, select the flag icon again and deselect Interest. ​ Expert The Expert flag recognizes deep expertise in a skill. Expert flags are applied by your manager or an administrator — you cannot apply the Expert flag to yourself. When the Expert flag is applied to you for a skill, it signals to your team and organization that you are a recognized authority in that area. By default, the Expert flag also grants training approval rights — you can approve or deny training requests for skills where you are flagged as Expert. Your organization’s admin can enable training approval rights on any custom flag using the Trainer Permission toggle in Settings > Flags . Note: If you believe you should be recognized as an Expert for a skill, speak with your manager. Expert flags are applied at their discretion. ​ Mentor The Mentor flag identifies you as someone who can guide and support others in developing a skill. Like the Expert flag, the Mentor flag is applied by your manager or an administrator. When the Mentor flag is applied to you for a skill, it signals to your team that you are available as a coaching resource in that area. Colleagues looking to develop that skill can identify you as a point of contact. ​ Applying Flags Across Sections and Careers Flags in SkillsDB can be applied at three levels, giving you a flexible way to communicate inten --- ## Skill Gaps URL: https://help.skillsdb.com/core-concepts/skill-gaps Quick Summary: A skill gap exists when your proficiency grade for a skill falls below the benchmark grade required for your Career. SkillsDB identifies these gaps automatically, displays them with color-coded indicators on the Skills page, and surfaces learning resources to help you close them. ​ Overview A skill gap is the difference between your current proficiency level for a skill and the benchmark grade your organization expects for that skill in your Career. SkillsDB calculates this comparison automatically: for every skill assigned to your Career, the system compares your recorded grade against the benchmark set for your role and level. When your grade falls short of the benchmark, the skill is identified as a gap. Skill gaps exist to give you and your manager a clear, objective picture of where your current proficiency does not yet meet the requirements of your role. Rather than relying solely on informal performance conversations, skill gap data provides a structured measurement that connects your personal development directly to your Career expectations. Your skill gaps are visible to you, your manager, and administrators. Your manager can use skill gap data to assign targeted learning resources, prioritize development discussions, and monitor your progress over time. You can use your own gap data to guide your learning priorities, decide which skills to focus on, and demonstrate growth. All employees can view their own skill gaps. No special permissions are required to see or act on your own gap data. ​ How Skill Gaps are Calculated A skill gap is calculated by comparing your grade for a skill against the benchmark grade set for that skill within your assigned Career. Your grade is determined by assessments: Self-assessment grade — the proficiency level you recorded for yourself during a self-assessment Manager grade — the proficiency level your manager recorded for you during a manager assessment When a grade has been recorded, SkillsDB uses it to compare against the benchmark. When no grade has been recorded yet, the skill appears as ungraded and no gap calculation is performed. The benchmark grade is the minimum proficiency level your organization expects for a given skill at your Career and level. Benchmarks are configured by your administrator or manager. They may vary by level — for example, the benchmark for a skill might be Level 2 for a junior role and Level 4 for a senior role. If your grade is below the benchmark, a gap exists. If your grade meets or exceeds the benchmark, no gap exists. Note: Benchmarks are set by your organization’s administrators or managers. If you believe a benchmark is incorrect for your role, contact your manager or administrator. ​ Understanding the Grade Indicators On the Skills page and in the career detail view, each skill displays a colored grade badge that shows your gap status at a glance. Color Meaning Red Your grade is below the benchmark — a skill gap exists Green Your grade meets the benchmark — no gap Blue Your grade exceeds the benchmark No badge / ungraded No grade has been recorded for this skill yet Red grade badges identify your current skill gaps. Green and blue badges confirm that a skill meets or exceeds its benchmark. These same color indicators appear in the Skills Matrix, which managers and administrators use to view skill gaps across their entire team. ​ Viewing Your Skill Gaps To see your skill gaps: Select Skills from the left sidebar navigation. The Skills page opens on the All Skills tab by default, showing your assigned Careers with a count of skills in each. Select a Career row to open the career detail view. In the career detail view, each skill row displays your self grade, your manager’s grade, and the benchmark grade. Skills where your grade falls below the benchmark show a red grade badge. To view all of your skills across all Careers at once, select the All Skills row at the top of the Skills table. This opens a combined view of every skill in every Career assigned to you. Note: Skill gaps only appear for skills that have a benchmark configured for your Career and level. Skills without a benchmark show your grade but do not display a gap indicator. ​ Addressing Your Skill Gaps Through Upskilling The Upskilling view connects your skills to learning resources that can help you close your gaps. To access Upskilling: Select Skills from the left sidebar navigation. At the top of the page, select the Skills breadcrumb to open the view dropdown. Select Upskilling from the dropdown. The Upskilling view lists your skills alongside any learning resources associated with them. Select a skill row to expand it and see the available resources. You can add a resource directly to your Learning Plan from this view. You can filter the Upskilling view to focus your work: All — Shows every skill that has learning resources available in the library In Progress — Shows only skills where you already have an active learning resource in your Learning Plan Use the Upskilling view to discover resources targeted at your skill gaps and to track what you are actively working through. Tip: Start on the career detail page to identify which skills are red (below benchmark), then switch to Upskilling to find learning resources for those specific skills and add them to your Learning Plan. ​ Using the Focus Flag to Prioritize a Skill If you want to mark a specific skill as a priority — for example, a skill where you have a significant gap — you can apply a Focus flag to it. Focus-flagged skills appear in the Highlights section on the Skills page, making them easy to find and monitor without drilling into a specific Career. To apply a Focus flag: Select Skills from the left sidebar navigation. Select a Career row to open the career detail view. On the skill row you want to prioritize, open the actions menu and select Add Focus . The Focus flag is self-applied — you do not need manager or administrator permission to flag your own skills. To rem --- ## Skills Matrix URL: https://help.skillsdb.com/core-concepts/skills-matrix Quick Summary: The Skills Matrix is an interactive grid that maps every employee in a career role against every skill in that role. Use it to compare self-assessments against manager grades, measure performance against benchmarks, and identify skill gaps across your team at a glance. ​ Overview The Skills Matrix is SkillsDB’s primary tool for understanding how proficient your workforce is across the skills in a given career role. The matrix organizes data as a grid: each row represents a person, each column represents a skill, and each cell displays that person’s grade for that skill. This structure lets administrators and managers instantly see where employees meet, exceed, or fall below role expectations — without needing to open individual profiles or run separate reports. The Skills Matrix draws on assessment data submitted by employees (self-assessments) and managers (manager assessments). Each grade in the matrix reflects either the employee’s self-reported proficiency or the manager’s evaluation, depending on which grade tab is active. You can toggle between these two perspectives at any time. The matrix also displays benchmark grades — the target proficiency level set for each skill in the role — so you can compare actual grades directly against expectations. Beyond proficiency grades, the Skills Matrix includes three alternative views: the Training Matrix (which shows training completion dates), the Skills Flag Matrix (which shows designations like Expert and Mentor applied to each person’s skills), and chart views for aggregate pattern analysis. All views share the same navigation, filtering, and export tools. Administrators have full access to the Skills Matrix for all career roles in the organization. Managers can access the matrix for roles assigned to their team, depending on the organization’s settings configuration. ​ Prerequisites Before using the Skills Matrix, ensure the following: Permission level : Administrator role, or Manager access with the Skills Matrix feature enabled in your organization’s settings Career role setup : At least one career role has been configured in Library > Careers with skills assigned and benchmark grades set Employee assignment : Employees have been assigned to the career role so they appear as rows in the matrix Note: The Skills Matrix reflects assessment data. If employees have not yet completed self-assessments and managers have not submitted manager assessments, most cells will display as Unassigned. See Assessments for guidance on creating and running assessment cycles. ​ Navigating to the Skills Matrix The Skills Matrix is accessed through the career details in the Library. Select Library from the left sidebar navigation. Select Careers to open the careers list. Select the career role you want to analyze. In the career details panel, select Skills Matrix . The Skills Matrix opens for the selected career role. The page title reads Analytics / [Role Name] . To switch to a different career role without returning to the Careers list, use the career selector dropdown in the breadcrumb navigation at the top of the page. Select any career from the dropdown to load its matrix instantly. ​ Understanding the Matrix Layout The Skills Matrix is organized as a grid with two axes: Rows (people): Each row represents one employee assigned to the selected career role. The People column, pinned to the left side of the grid, shows each person’s name, job title, and role level badge (for example, “L1” or “L2”). Columns (skills): Each skill in the career role appears as a separate column. Skills are grouped by section — the category they belong to within the career. Section names appear as column group headers above the individual skill column labels. Cells (grades): Each cell at the intersection of a person and a skill shows that person’s grade for that skill. Grades are displayed as numeric badges and are color-coded to indicate performance relative to the benchmark for that skill: Color Meaning Green Exceeds Target — grade is higher than the benchmark Yellow Meets Target — grade equals the benchmark Red Below Target — grade is lower than the benchmark Empty Unassigned — no grade has been submitted for this skill The specific grade levels available in your organization (for example, 1 through 5, with labels such as “Beginner” through “Expert”) are configured by your administrator in the grading scale settings. Benchmark grades for each skill are set per career role in Library > Careers . ​ Switching Between Views The Skills Matrix page offers five views. To switch between views, use the view selector dropdown in the breadcrumb navigation area at the top of the page. ​ Skills Matrix (default) The Skills Matrix view is the default. It displays numeric proficiency grades for each person-skill combination. Grades reflect either the manager’s assessment or the employee’s self-assessment, depending on the active grade tab. See Toggling Between Manager and Employee Grades below for details on switching between grade sources. ​ Training Matrix The Training Matrix view replaces proficiency grades with training completion dates. Each cell shows the date an employee completed training for that skill, or “NA” if no training record exists. Selecting a cell in the Training Matrix opens the Skill-Based Training Records modal for that person-skill combination. The modal displays existing training records — including the trainer’s name, training date, and attached documents — and allows you to add new training entries. ​ Skills Flag Matrix The Skills Flag Matrix view shows the skill flags applied to each person for each skill in the role. Flags appear as colored badges inside each cell: Flag Badge color Meaning Expert Yellow Person is designated as an Expert for this skill Mentor Blue Person is designated as a Mentor for this skill Focus Green Person has marked this skill as a development focus Interest Purple Person has expressed interest in learning this skill A cell --- ## Surveys URL: https://help.skillsdb.com/core-concepts/surveys Quick Summary: Surveys let administrators collect structured data from employees — feedback, certifications, skill information, and more. Create a survey from a template, target specific groups, track response progress in real time, and view individual or aggregate results. ​ Overview Surveys in SkillsDB are configurable questionnaires that administrators send to employees to collect structured data. Common uses include gathering feedback, capturing certification details, confirming skill proficiency, and running periodic engagement checks. Surveys are built from templates — reusable question sets that can be shared across multiple surveys. Once a survey is created from a template, it is distributed to a target audience: the entire organization, specific departments or teams, or a manually selected group of individuals. Administrators can launch a survey immediately or schedule it for a future date, then track response progress and view detailed results as responses come in. Surveys integrate with SkillsDB’s certifications system. When a survey includes a Certification Update question type, responses captured during the survey flow directly into the respondent’s certification record, eliminating the need for separate data entry. Administrators can create and manage all surveys. Managers can view survey results for their direct reports. Employees receive surveys via their My Profile section and respond from there. ​ Prerequisites Before creating a survey, you need: Permission level : Administrator role Survey template : At least one survey template created in SkillsDB, or the ability to create a new one during the survey creation wizard Target population : Employees imported and organized in SkillsDB so you can target by department, team, or org structure Note: The Surveys feature must be enabled for your SkillsDB account. Contact your account manager if you do not see Surveys in the Manage sidebar menu. ​ Understanding Survey Templates A survey template is a reusable collection of questions that forms the basis of one or more surveys. Templates let you define a question set once and use it across multiple survey instances — for example, a quarterly feedback template that gets re-launched each quarter. ​ Template visibility Templates are either Private (visible only to the creator) or Visible to all administrators. When creating a new survey, you can select any template that is visible to you. ​ Question types Templates are built from individual questions, each with a defined question type. The following question types are available: Question type Description Supports multiple responses Multiple choice Respondent selects an option from a predefined list. Options are lettered, so respondents can press a letter key to select. Yes Drop down Respondent selects one option from a menu that reads Choose an option… when closed No Text response Free-text answer No File upload Prompts the respondent to upload one or more documents No Confirm certifications Captures certification details and supporting attachments. Available only when certification responses are enabled for your organization, and limited to one per survey. No Note: Rating , Yes/No , and Likert questions still display and accept answers in surveys that already contain them, but they are not offered when building a new survey. Individual questions can be marked as required , preventing respondents from submitting the survey without answering them. Multiple choice questions can be configured to allow the respondent to select more than one option. Note: Certification Update questions capture the respondent’s certification ID, issue date, expiration date, and supporting attachments (up to five files per response; accepted formats: .jpg, .png, .pdf, .docx, .xlsx, .txt, .csv; maximum 10 MB each). Responses from Certification Update questions automatically update the respondent’s certification record in SkillsDB. ​ Creating a Survey Surveys are created through a five-step wizard. Navigate to Company > Surveys and select Create Survey to begin. ​ Step 1: Select a template Choose an existing template from the list, or create a new template to use for this survey. Templates marked as Visible to all appear alongside any templates you created personally. If you are creating a new template, define the template name, visibility setting, and add the questions you want to include. Questions are added in order and can be reordered within the template. ​ Step 2: Enter basic details Enter the core information for this survey instance: Name (required) — Up to 100 characters. This name appears in the survey list and in the email notification sent to respondents. Description (optional) — Up to 1,000 characters. Provides context to respondents about the purpose of the survey. Due Date (optional) — The date by which responses are expected. The survey remains open after this date unless manually ended. Select Next to continue. ​ Step 3: Choose your target audience Select who will receive this survey. Three targeting methods are available: All people — The survey is sent to every active employee in the organization. Org structure — Turn off Send to All People to choose groups from the compact Organization , Location , and Work Schedule sections. Open a field and select one or more groups. The groups-picked count below these fields counts selections, not recipients. Available org dimensions include: Department Business Unit Division Team Country City Site Shift Business Region Selecting multiple values within the same dimension uses OR logic (a person in either Department A or Department B is included). Selections across different dimensions use AND logic (a person must be in the selected department AND the selected team). Manual selection — Add specific individuals by name. Use this when the target group does not map neatly to an org structure segment. You can combine manual additions with org structure selections. After launch, you can also add or remove ind --- ## Training Approvals URL: https://help.skillsdb.com/core-concepts/training-approvals Quick Summary: Training approvals are the verification process that lets employees record skill training and have it reviewed by an authorized approver — such as a manager, admin, or designated subject matter expert — before it counts as verified in SkillsDB. ​ Overview Training approvals are how SkillsDB verifies that an employee’s training record is legitimate and substantiated. When an employee records training for a skill, that record enters a pending state and must be reviewed by an authorized approver before it is considered officially verified. Only approved training records count toward a user’s trained status for a skill. This process helps organizations maintain accurate, trustworthy skill records by ensuring training completions are supported by evidence and reviewed by someone with oversight — not simply self-reported. Training approvals connect directly to each employee’s skills profile, so an approval is reflected in team reports, skill gap analysis, and the training matrix. Training approvals are relevant to three groups: employees who submit training records, managers and admins who review and action those records, and subject matter experts (SMEs) who hold the Expert flag with Trainer Permission and can be designated as approvers by their colleagues. ​ Prerequisites Before submitting or actioning training approvals, confirm the following: Submitting a training record : Any SkillsDB user can submit training for skills on their profile Approving as a manager or admin : Manager or Administrator role required Approving as an SME : An admin must have enabled Trainer Permission on the Expert skill flag, and a manager must have applied the Expert flag to you for the relevant skill ​ How Training Approvals Work Training approvals follow a defined workflow with four key stages: An employee submits a training record for a skill with supporting evidence The record enters Pending status and appears in the authorized approver’s Inbox The approver reviews the record and selects Approve or Reject The training record moves to a terminal state of Approved or Rejected Status Meaning Can action Pending Submitted, awaiting review Yes — approver can Approve or Reject Approved Verified by an authorized approver No — record is read-only Rejected Not verified; evidence was insufficient No — employee can resubmit a new record Expired Approved training has passed its expiration date No — employee can renew training Note: Once a training record is Approved or Rejected, it becomes read-only. The dialog shows who actioned the record and when. Approved training may expire over time based on settings configured by your admin. See Training Expirations for details. Who can approve training Three groups of people are authorized to approve training in SkillsDB: Managers can approve training records submitted by their direct reports Administrators can approve any training record across the organization Expert flag holders with Trainer Permission can approve training for the specific skills where they are designated as Experts — but only if an admin has enabled the Trainer Permission setting on the Expert skill flag If an employee does not select a delegated approver (SME) when submitting, any manager or admin can review and action the request from their Inbox. ​ Submitting a training record Employees submit training records from their skills profile. Use this process when you have completed training for a skill and want it recorded and verified in SkillsDB. Navigate to your skills profile and locate the skill you trained on Select Submit Training on the skill In the training submission modal, fill in the following fields: Date of Training (required): The date the training took place Trainer (optional): The name of the person or organization that delivered the training Text Evidence (may be required): A written description of the training completed Attachments (may be required): Evidence files such as certificates or course completions SME (optional): A subject matter expert to designate as your specific approver Select Submit When the submission is complete, the training record is created with Pending status. Your designated SME (or any manager or admin) receives the request in their Inbox for review. Note: Whether Text Evidence and Attachments are required depends on your organization’s settings, configured by an admin. Accepted file types are: .jpg, .png, .pdf, .docx, .xlsx, .txt, .csv — maximum 10 MB per file. Tip: If you know a specific subject matter expert should evaluate your training, select them in the SME field. This routes your request directly to them and helps ensure it’s reviewed by the most qualified person. ​ Reviewing and actioning training requests Managers, admins, and designated SMEs receive training approval requests in their Inbox . Use this process to review a pending training record submitted by an employee. Navigate to Inbox from the left sidebar Select the Approvals category to filter for pending training requests Select a training approval item to open the Training Approval dialog Review the details presented in the dialog: Employee name and skill name Date of training Trainer name (if provided) Text evidence (if provided) Attachments (select to preview or download) Delegated approver (if an SME was specified by the employee) Select Approve to verify the training record, or Reject to decline it When you approve a training record, its status changes to Approved and the record is reflected in the employee’s skills profile. When you reject a record, its status changes to Rejected and the employee can resubmit with updated evidence. Important: Approving or rejecting a training record cannot be undone. Once actioned, the record is read-only and displays who made the decision and when. ​ Selecting a delegated approver (Expert) When submitting a training record, you can optionally select a subject matter expert (SME) as a delegated approver. This is useful when a specific expert is bett --- ## Training Expirations URL: https://help.skillsdb.com/core-concepts/training-expirations Quick Summary: Training expirations automatically track whether completed skills and certifications are still current. This article explains expiration statuses, where to find them in SkillsDB, and what to do when training expires. ​ Overview Training expirations are how SkillsDB tracks whether completed skills and certifications are still current. When an administrator configures an expiration period for a skill or certification, SkillsDB automatically calculates an expiration date based on the date the training was approved. As that date approaches or passes, the training’s status updates to reflect whether it is still valid — without any manual action required. Expirations exist because many skills and certifications require periodic renewal to remain meaningful. Training completed two or three years ago may no longer reflect someone’s current knowledge, especially in fast-changing fields like technology, safety compliance, or regulated industries. By surfacing expiration data across the platform, SkillsDB helps individuals stay on top of their own renewal needs and gives managers a clear picture of where their team’s training records may be out of date. Training expirations apply to two types of records in SkillsDB: Skill-based training — linked to specific skills within a career and tracked through the Training Matrix Certifications — formal credentials assigned and managed through the Certifications section Both follow the same four-status expiration model, but certifications use a slightly longer warning window to account for the additional lead time often required to renew a formal credential. Standard users can view their own training expiration status throughout their skills profile and certifications page. Managers can view expiration status for their entire team in the Training Matrix. Administrators configure the expiration periods for skills and certifications at the organization level. ​ Understanding Expiration Status SkillsDB displays one of four expiration statuses for each piece of training. The status appears as a color-coded badge throughout the platform wherever training records are shown. Status Badge color Meaning Valid Green Training is current and not approaching expiration. Expiring Soon Yellow Training is approaching its expiration date and should be renewed. Expired Red Training has passed its expiration date and is no longer current. No Expiration Gray No expiration period has been configured for this training. How “Expiring Soon” is calculated: For skill-based trainings: within 30 days of the expiration date For certifications: within 30 days of the expiration date Note: Skill-based training and certifications both use a 30-day warning window, so the “expiring soon” signal is consistent across the product. When training is in Expiring Soon or Expired status, a warning icon appears alongside the badge. Hovering over the badge shows a tooltip with the exact expiration date and the number of days remaining — or the number of days since expiration for records that have already expired. ​ Where to See Training Expirations Expiration status appears throughout SkillsDB in several locations, depending on the type of training and your role. My Certifications Your certification expirations are visible from the My Certifications page. Select Certifications from the left sidebar. The Expires column displays the expiration status badge for each certification. To narrow the list, select the Expires filter and choose from Expired , Expiring Soon , Valid , or No Expiration . Your skills profile For skill-based trainings linked to a career, expiration status appears alongside individual skills in the career detail view. Navigate to Profile > Skills . Select a career to open the career detail view. Skills with an expiration period configured display a training expiration badge. Skills with no expiration period show no badge or a gray “No Expiration” badge. Training Matrix (managers) Managers can view expiration status for their team across all skills in the Training Matrix. See Tracking team expirations below. ​ Using the Expirations View Team > Training has a dedicated Expirations view alongside All Activity and Training Matrix . Select Expirations from the view switcher in the breadcrumb to open it. The view lists every training record that carries an expiration date, grouped for review. Four grouping options appear as chips above the table: Grouping What it groups by By Person Each team member, with their email and a count of affected records. This is the default. By Career Each career that contains expiring training By Skill Each skill with expiring training By Section Each career section with expiring training Each row shows Career , Skill , Section , Status , and Expiration . Status is one of Approved , Awaiting Approval , or Renewal Required , and the Expiration column shows a warning icon next to the date once a record needs attention. Use Filter to narrow the list, Collapse All to fold every group at once, and Export to download the current view. Scope tabs in the breadcrumb control which people are included. ​ What Happens When Training Expires When training reaches Expired status, SkillsDB updates the badge to red and displays a warning icon wherever that training record appears. The training record is not deleted — the original approval date, training date, and full history remain intact. The expiration status is a visual signal, not a record deletion. An expired training does not automatically trigger a new training request. What happens next depends on the type of training: For certifications: Contact your manager or administrator. They can assign a certification renewal, which creates a new certification record while preserving the full history of the original. Once approved, the expiration countdown resets from the new certification’s issued and expiration dates. For skill-based training: Contact your manager. Managers can initiate a new training request from --- ## Training Matrix URL: https://help.skillsdb.com/core-concepts/training-matrix Quick Summary: The Training Matrix is a grid view that maps every skill against every team member, showing each person’s most recent training date and status at a glance. Use it to monitor compliance, identify expiring records, submit training evidence, and export reports. ​ Overview The Training Matrix is a cross-reference view in SkillsDB that displays training records across your team. Each row represents a skill and each column represents a team member. Each cell shows that person’s most recent training date for that skill, along with a color-coded status indicator. The Training Matrix is distinct from the Skills Matrix. The Skills Matrix shows proficiency grades — how well someone performs a skill. The Training Matrix shows training completion — whether someone has submitted evidence of completing training for a skill, and whether that training is still current. The two views complement each other: proficiency tells you what people can do, and training records tell you when they formally completed training to confirm it. The Training Matrix is most valuable when your organization tracks training against specific skills with regulatory, safety, or certification requirements, particularly where training records have expiration dates that must be monitored. Administrators can view and manage training data for all employees in the organization. Managers can view and manage training data for their direct reports and their full organizational hierarchy. Users designated as Experts for a skill can also access the Training Matrix for the skills where they hold Expert status. ​ Navigating to the Training Matrix The Training Matrix is accessed from the My Team training section of SkillsDB. Select Team from the left sidebar navigation. In the view dropdown at the top of the page, select Training Matrix . The page defaults to the Direct Reports tab. Use the tabs at the top of the matrix to switch between scopes. ​ Understanding the Matrix ​ Reading the grid The Training Matrix uses a row-per-skill, column-per-person layout: Element Description Skill column (pinned left) The name of each skill, along with any skill flag badges assigned to it Person columns One column per team member, labeled with the person’s full name | Cells | The training date and status for that person-skill combination | ​ Interpreting cell values Each cell in the matrix shows one of the following states: Cell display Meaning A date (e.g., 2025-03-15 ) The person has a training record for this skill on that date Approved badge (green) The training record has been reviewed and approved Pending badge (yellow) A training record has been submitted and is awaiting approval Rejected badge (red) The training submission was reviewed and rejected Date in a yellow chip Approved training that will expire within 30 days Expired badge (red) Approved training has passed its expiration date NA badge (gray) The skill is not assigned to this person’s role Each cell shows the training date inside a single colored chip — green when approved and current, yellow when the training expires within 30 days, and red once it has expired. Expiration takes priority over approval status, so an approved record that is expiring shows the yellow chip. Hover the chip to see the exact expiration message. Note: Expiration settings are configured per skill by your administrator. If no expiration period is set for a skill, approved training does not display an expiration badge and remains valid indefinitely. See Training Expirations for details on how expiration is calculated. ​ Selecting a view scope Three tabs control which team members appear as columns in the matrix: Tab Who appears Who can access it | Direct Reports | Only your immediate direct reports | Managers and Admins | | My Org | Everyone in your full organizational hierarchy | Managers and Admins | | All | All employees in the entire organization | Admins only | ​ Filtering and Sorting ​ Lenses Lenses are toggle filters that change which records you see. Three lenses appear in the toolbar above the matrix: Filter What it does Earliest Training Dates Reorders the skill rows so skills with the most recent training activity appear first, with skills that have no training date last Has Training Date Hides cells that have no training date, keeping NA cells visible. Skill rows where every cell disappears are dropped from the view Inactive Users Includes archived or deactivated employees in the matrix ​ Builder filters The filter panel lets you narrow the matrix by organizational attributes. Select the filter icon to open the panel. Filter Description Selection type Role Filter by job role (career). Only careers that have training dates enabled appear in this list. Single select Department Filter by department Multi-select Division Filter by business division Multi-select Region Filter by geographic region Multi-select Label Filter by labels assigned to people Multi-select Tip: Combine the Career filter with Has Training Date turned on to strip out cells with no recorded training, leaving only the skills and people that already have training activity — a fast way to focus a review on live records. ​ Managing a Training Record Clicking any cell in the Training Matrix — except an NA cell — opens the Manage Skill Training panel for that person-skill combination. From this panel, you can view the full training history for that person and skill, submit a new training record, edit a pending submission, or renew an approved record. ​ Submitting a new training record To submit a training record for a person-skill combination: Click the cell for the person and skill you want to update. In the Manage Skill Training panel, select Add training . Complete the training record form: Training Date (required) — Select the date the training was completed. Trainer Name (optional) — Enter the name of the trainer or instructor. Text Evidence (required if configured for this skill) — Provide a written description of the traini --- ## Upskilling URL: https://help.skillsdb.com/core-concepts/upskilling Quick Summary: Upskilling in SkillsDB is a focused view that bridges skill gaps and learning resources. When admins attach resources to skills in the Learning Library, those skills automatically surface in every user’s Upskilling view, giving the whole organization a clear path from gap to growth. ​ Overview Upskilling is a skill development feature in SkillsDB that surfaces skills alongside their associated learning resources. Rather than showing every skill a user holds, the Upskilling view shows only skills that have learning resources attached — creating a focused, action-oriented workspace for professional development. The feature exists to answer a fundamental question employees and managers face: “I know I have a skill gap — now what?” Instead of leaving users to search the Learning Library independently, Upskilling presents development opportunities in context, directly against the skills they are already being measured on. As an administrator, you enable Upskilling by populating the Learning Library and linking resources to skills. Once resources are attached to a skill, that skill automatically appears in the Upskilling view for any user who holds it. No additional configuration is required. Upskilling is used by all three role levels. Employees use it to find and add development resources to their learning plan. Managers use it to assign resources to their direct reports. Global admins use it to edit library resources directly. Understanding this flow helps you design your Learning Library to maximize adoption of your upskilling program. ​ How Upskilling Works The Upskilling view is driven entirely by the Learning Library. The connection works as follows: An admin adds a learning resource to the Learning Library under Library > Training . That resource is linked to one or more skills in the library. Any user who has that skill in their skills profile sees the skill appear in their Upskilling view. The user can then add the resource to their learning plan or, if a manager, assign it to a team member. Note: A skill only appears in the Upskilling view if it has at least one learning resource attached to it. Skills without resources do not appear, even if the user holds that skill. The Upskilling view is not a separate module — it is a filtered perspective on a user’s existing skills, contextualized with available learning resources. This means the quality of your upskilling program is directly tied to the completeness of your Learning Library. ​ Setting Up Upskilling for Your Organization Administrators control what appears in the Upskilling view by managing the Learning Library. To ensure skills appear in the Upskilling view: ​ Step 1: Add resources to the Learning Library Navigate to Library > Training . Select + New to create a new learning resource. Enter the resource details, including the Title , Type , Provider , and URL if applicable. Select Save . Tip: Resources with clear titles, descriptions, and a direct URL drive the highest engagement. Users are more likely to add resources to their learning plan when they can immediately understand what they will learn and how to access it. ​ Step 2: Link resources to skills After creating a resource, link it to one or more skills so the resource appears in the Upskilling view for users who hold those skills. Navigate to Library > Skills . Select the skill you want to link the resource to. In the skill detail view, locate the Learning Resources section. Add the relevant resource from the library. When a resource is successfully linked to a skill, that skill will appear in the Upskilling view for any user whose skills profile includes that skill. ​ Accessing the Upskilling View The Upskilling view is accessed from the Skills page, which is available to all users. Select Skills from the left sidebar. In the breadcrumb navigation at the top of the page, select Upskilling . The page switches from the All Skills view to the Upskilling view, which shows only skills that have associated learning resources. Note: If no skills appear in the Upskilling view, it means no learning resources have been linked to that user’s skills. Review the Learning Library to confirm resources are attached to the relevant skills. ​ Understanding the Upskilling Table The Upskilling table lists skills as collapsible rows. Each skill row shows the skill name, any labels applied to that skill, and a Not Started progress badge indicating no resources in that skill have been added to the user’s learning plan yet. Selecting a skill row expands it to reveal the individual learning resources attached to that skill. Each resource row displays the following columns: Column Description Resource The title of the learning resource Label Labels applied to the resource for categorization Type The resource type (e.g., course, video, article) Progress The resource’s current status in the user’s learning plan Selecting a skill row again collapses it and hides the resource rows. ​ Filtering the Upskilling view A filter dropdown at the top left of the Upskilling view controls which skills are displayed: Filter What it shows All All skills that have at least one attached learning resource In Progress Skills where the user has at least one resource currently in progress in their learning plan To apply a filter, select the filter dropdown button and choose the desired option. ​ Taking Action on Resources Users interact with resources by selecting the checkbox next to one or more resource rows. When at least one resource is selected, a floating action bar appears at the bottom of the screen. The actions available in the floating action bar depend on the user’s role: Action Who can use it What it does Add All users Adds the selected resource(s) to the user’s own learning plan. Disabled if all selected resources are already in the learning plan. Assign Managers and above Opens the Assign window to assign the selected resource to one or more team members. Edit Global admins only Opens t --- ## Version History URL: https://help.skillsdb.com/core-concepts/version-history Quick Summary: Skills in SkillsDB keep a full version history of every change to the skill’s name and description. Administrators can view all past versions from the Activity tab on the skill detail page, and see exactly what the skill looked like at any point in its history. ​ Overview Version History creates a persistent record of every change made to a skill in SkillsDB. Each time an administrator edits a skill’s name or description, SkillsDB captures a new version that records what changed, who changed it, and when. No edits are lost — every historical state is preserved. The first time a skill is created, SkillsDB stores a Baseline version. Every subsequent edit creates an Updated version on top of that baseline. Together, these form an ordered timeline visible on the Activity tab of any skill detail page. Version history is an audit and reference tool. Use it to: Review what a skill’s name or description looked like at a previous point in time. Understand why people were trained against the earlier definition of a skill. Investigate changes when someone’s training status or grade unexpectedly shifts. Provide evidence of skill definition changes during audits or compliance reviews. Version history is administrator-facing and appears on individual skill detail pages. Employees and managers see the current version of a skill throughout the product — they do not see the version timeline. ​ Prerequisites Before you view or use version history, you need: Permission level: Administrator role in SkillsDB Setup requirement: At least one skill in your organization (a skill must exist before it has history) Access: Navigate to Library > Skills , then open any skill ​ How Versions Are Created Versions are created automatically whenever an administrator edits a skill. You do not manually start a version — SkillsDB captures one for every change. Event Version type When it happens Baseline The first recorded version of a skill Created automatically when a skill is first created, or when version tracking is enabled for an existing skill Updated A new version recorded after an edit Created every time an administrator saves changes to a skill’s name or description Each version captures: Name — the skill’s name at the time of the version Description — the skill’s description at the time of the version Version date — the exact timestamp when the change was saved Edited by — the administrator who made the change Change note — an optional free-text explanation an admin can add when editing the skill Versions are stored per-skill. Each skill has its own independent timeline. ​ Viewing Version History Version history lives on the Activity tab of the skill detail page. The Activity tab combines version history with other skill-level events into a single chronological timeline. To view a skill’s version history: 1 Open the skill Navigate to Library > Skills from the left sidebar, then select the skill name from the table. 2 Open the Activity tab In the skill detail view, select the Activity tab. The timeline loads with the most recent event at the top. 3 Expand a version Each version entry shows a summary — who edited the skill and when. Select Show content on any entry to reveal the full name and description captured in that version. Select Hide to collapse it again. The Activity tab shows the total number of entries at the top (for example, “12 entries”). Use the timestamp next to each entry to find a specific version — hover over the relative time (“2 days ago”) to see the full date and time. ​ What each entry shows Each version entry in the timeline displays: A colored event type badge — Baseline (gray) for the initial version, or Updated (blue) for subsequent edits. A short event description summarizing the change. The editor’s name (or “System” if the change was automated) and how long ago the change occurred. An affected user count (when relevant), showing how many people’s records were impacted. A Show content button to expand the saved name and description for that version. ​ Renewing Training After a Skill Change When you change a skill’s definition, training that people already completed may no longer reflect the current requirements. SkillsDB offers a Renew Training action that resets training status for the skill across affected users, so they re-complete training against the updated definition. Renew Training is only available to administrators and only appears when the current version of the skill is eligible for renewal. To renew training for a skill: 1 Open the Activity tab Navigate to Library > Skills , select the skill, then open the Activity tab. 2 Select Renew Training If Renew Training is available for this skill, a Renew Training button appears in the top right of the Activity panel. Select it to open the renewal dialog. 3 Confirm the action Review the number of affected users, select the appropriate renewal option, and confirm. The action is logged as a new Renew Training entry in the Activity timeline. Warning: Renewing training resets the training approval status for every person who has been approved for this skill. People will need to submit training again. Use this action only when a skill change is significant enough to require re-verification of competency. Renewals are permanently recorded in the Activity timeline alongside version history, so you always have a record of which skill updates triggered a mass renewal. ​ Common Questions What changes to a skill create a new version? Edits to a skill’s name or description create a new version. Changes to other skill attributes — such as which careers the skill is attached to, flag assignments, or training settings — are tracked separately in the Activity tab but do not create a new name/description version entry. Can I edit or delete a previous version? No. Version history is immutable. Past versions cannot be edited or deleted. This is intentional — the audit trail must remain tamper-proof to serve as reliable evidence of what t --- ## Careers URL: https://help.skillsdb.com/explore/careers Quick Summary: The Careers library lets you browse all Careers defined in your organization — the structured role definitions that group skills, benchmarks, and learning resources together. Use it to explore what skills and proficiency levels are expected in different roles and to understand how your own Career compares to others. ​ Overview Careers in SkillsDB are structured role definitions that describe what skills, proficiency benchmarks, and learning resources are associated with a given position in your organization. A Career groups skills into sections, assigns a benchmark grade to each skill at each level, and optionally links training resources that support development in that role. The Careers library is where you can browse all of the Careers your organization has defined. This is useful when you want to understand what skills are expected in your current role, explore what a different role in your organization requires, or identify the skills and benchmarks you would need to develop if you were interested in moving into a new Career. All employees can browse the Careers library. You do not need any special permissions to view Career definitions or to explore their skills, benchmarks, and linked learning resources. Administrators and managers have additional controls — including the ability to create, edit, and assign Careers — that are not available in the standard employee view. Note: The Careers library is only visible if your organization has enabled it. If you do not see Careers in your sidebar, contact your manager or administrator. ​ Navigating to the Careers Library To view the Careers library expand the Library section in the left sidebar navigation, then select Careers . The Careers page opens, showing a table of all Careers defined in your organization. ​ Understanding the Careers Table The Careers table shows a summary of each Career defined in your organization. Column Description Career The name of the Career. Select any row to open the Career detail page. Labels Any labels applied to the Career by your administrators. Type The category or type this Career belongs to, as configured by your organization. Assigned The number of employees currently assigned to this Career. You can organize the list using the grouping buttons at the top: Alphabetical (the default), Type , or None . To narrow down results, select Filter and choose from Career, Type, Labels, or People Assigned filters. You can also toggle column visibility using the Display button. ​ Opening a Career Detail Page To explore a Career in detail: Expand the Library section in the left sidebar and select Careers . Select any row in the Careers table to open that Career’s detail page. The detail page shows the full definition of the Career, including its skills, sections, benchmarks, and any linked learning resources. ​ Understanding the Career Detail Page The Career detail page is organized into two areas: the header and the skills table. Header area: The header shows: The Career name and description Updated or Created — the date the Career was last modified, or its creation date when it has not been modified Assigned — how many employees are currently assigned to this Career Type — the Career category configured by your organization (e.g., “Job Role”) Skills table: Skills in the Career are organized into named sections. Each section appears as a collapsible group, and each row in the section represents a skill. For each skill, the table shows: Skill name and description Labels — any labels attached to the skill Level columns — one column per level defined for the Career (such as Level 1, Level 2, Level 3). Each level column displays a colored badge (L1, L2, L3, etc.). When a benchmark grade is configured for a skill at a given level, the grade number appears in the corresponding column. When benchmark grades are shown, they tell you the minimum proficiency level expected for a person at that level in this Career. If you are assigned to this Career, your own skill grades are compared against these benchmarks to determine your skill gaps. ​ Viewing Learning Resources Linked to a Career Some Careers have learning resources linked to their skills and sections. Within each section, skills and learning resources are separated into two collapsible groups: Skills and Training . Each row in the Training group shows the resource’s title and description. Select a training row to open its record in Library > Training . Learning resources in the Career detail view are the same resources that appear in the Upskilling view when you browse your own Skills page. They represent content your organization has selected as recommended development resources for this Career. Note: To add a learning resource from a Career directly to your own Learning Plan, use the Upskilling view on the Skills page rather than the Careers library. See Building a Learning Plan for instructions. ​ Adding a Training Record from a Career Page If your organization has the training library enabled, you can add a training record directly from a Career detail page. This lets you log a training completion in the context of a specific Career and skill. To add a training record: Expand the Library section in the left sidebar and select Careers . Select the Career you want to log training against. On the Career detail page, select Training in the top right of the page. In the training dialog, search for the training resource or add a new entry, and complete the required fields. Submit the training record. Your submitted training record will be visible in your Skills profile and, where applicable, will appear in the Training Matrix for your manager to review and approve. Note: The Training button only appears on the Career detail page if your organization has the training library enabled and you do not have administrator access. Administrators use a different flow to manage training resources. ​ Common Questions What is the difference between a Career and a j --- ## Certifications URL: https://help.skillsdb.com/explore/certifications Quick Summary: The Certifications scope of Search lets you search your organization’s certification catalog and see which employees hold specific certifications — all from a single, filterable search interface. ​ Overview The Certifications scope of Search is a search tool for browsing certification information across your entire organization. It gives you two complementary views: you can explore the organization’s certification catalog to see what certifications exist and how many people hold them, or you can browse employee certifications to see who holds a specific certification and what their current status is. This is useful when you want to understand certification coverage in your organization — for example, identifying whether anyone on your team holds a required credential, checking expiration dates across a group of employees, or exploring what certifications your organization tracks before pursuing one yourself. The Explore Certifications page is separate from your personal certifications list. Your own certifications are managed from your profile. This page is for discovery across the broader organization. ​ Prerequisites Before you begin, make sure you have: Search access : Your account must have search permissions enabled. If you cannot see Search in the left sidebar, contact your administrator. ​ Exploring certifications in your org Navigating to Certifications Select Search from the left sidebar. In the scope selector row, select Certifications . The results area loads with the Certifications view active by default. Choosing between Certifications and Employee Certifications views The Certifications scope offers two distinct view modes, toggled from the Display menu: Certifications — Displays the organization’s certification catalog. Each row represents a certification, showing how many employees are assigned to it, its issuing authority, category, and type. Use this view to explore what certifications exist in your organization. Employee Certifications — Displays individual people and their certification records. Each row represents a person–certification pairing, showing their current status, expiration date, and how many days remain until expiration. Use this view to find out who holds a specific certification. To switch views: Select Display in the top right of the results area Under the display options, select either Certifications or Employee Certifications The results table updates immediately Searching and filtering results You can narrow results using the text search bar and structured filters: Enter a certification name or keyword in the search bar and press Enter — the term is added as a filter tag and results update automatically. To add structured filters, select Filter next to the search tags. Available filter types include organizational structure filters: Business Unit , Division , Department , Team Country , State , City , Site , Shift , Region Document Type To control how multiple filters are applied, toggle between Match all (results must meet every filter) and Match any (results meeting at least one filter). To remove a filter tag, select the x on the tag. To remove all filters, select Clear . Tip: Use the org structure filters to narrow results to a specific team or department. For example, filter by Department to see all certifications held by employees in a particular group. ​ Understanding Certifications View Results In Certifications mode, each row in the results table represents a certification in the organization’s catalog. The table displays: Column Description Name The certification name, with a certification icon Assigned The number of employees currently assigned to this certification Criteria Tags showing which filters or search terms this certification matched Match A percentage score showing how closely the result matches your search criteria Select any row to navigate to the certification’s detail page, where you can see a full list of employees assigned to it and their individual statuses. ​ Understanding Employee Certifications View Results In Employee Certifications mode, each row represents an individual employee’s certification record. Each row displays the employee’s name with the certification name shown below it, along with the search criteria tags and match percentage. Column Description Person The employee’s name, with the certification name displayed below Criteria Tags showing which filters or search terms this result matched Match A percentage score showing how closely the result matches your search criteria Select a person’s row to navigate to their profile page. Certification statuses In Employee Certifications view, each record displays one of the following statuses: Status Meaning Assigned The employee has been assigned the certification but has not yet submitted details Awaiting approval The employee has submitted details and is awaiting manager review Approved The certification has been approved by a manager Denied The submission was reviewed and denied Expired A previously approved certification has passed its expiration date Note: A certification expiring within 30 days is flagged with a yellow indicator on the expiration date in the certification detail view. The Days until expiration column in Employee Certifications view makes it easy to spot certifications approaching expiry. ​ Viewing Certification Details Selecting a certification in the Certifications view opens the certification’s detail page in the library. This page shows: A summary of the certification (name, description, issuing authority, category, type) A table of all employees assigned to the certification, including their status, expiration date, and ID number From the certification detail page you can review the full population assigned to a certification and identify employees whose status is Expired or Expiring Soon. ​ Common Questions What is the difference between the Certifications and Employee Certifications views? The Certifications view shows --- ## Find Experts URL: https://help.skillsdb.com/find-experts Quick Summary: Use the Search page to find people with specific skills, locate training resources, explore careers, and identify certified employees across your organization — all from a single, filterable interface. ​ Overview The Search page is SkillsDB’s organization-wide discovery tool. It lets you search across people, skills, training resources, careers, and certifications simultaneously, then narrow results with targeted filters to find exactly who or what you need. Search is built for situations where you already know what you’re looking for — a subject matter expert in a particular skill, someone with a specific certification, or a career path that aligns with a set of competencies. Instead of browsing through multiple sections of the product, you can describe the criteria and let Search surface matching results ranked by relevance. The Search page is accessible to all users, though administrators can restrict access to people search features based on your organization’s settings. All users can search skills, training, careers, and certifications. Access to people search depends on your organization’s configuration. ​ Navigating to Search Select Search from the left sidebar. The Search page is located at the top level of SkillsDB navigation. Note: If you previously bookmarked the old /explore URL, SkillsDB automatically redirects it to the current /search path. ​ Performing a Basic Search ​ Searching by keyword Use the search input to find results by name or keyword across all resource types. Select the search input at the top of the page (placeholder text reads “Search people, training and more…”). Type a keyword — for example, a skill name, a person’s name, or a training course title. SkillsDB displays a suggestion dropdown after you type one or more characters. Select a suggestion from the dropdown, or press Enter to run a broad text search. When you select a suggestion, SkillsDB adds it as a structured filter tag. Structured filters produce more precise results than plain text searches because they match against specific database records rather than general text. ​ Using type filters By default, Search returns results across all resource types ( All ). Use the type filter buttons to limit results to one category: Filter button Returns All People, training, skills, careers, and certifications — grouped by type People Employees and users in your organization Training Training resources from your organization’s library Skills Individual skills from the skills library Career Career paths configured in your organization Certifications Certification records from the certifications library Select a type filter button to scope your search. The active filter is highlighted. Select the active filter again to return to All . ​ Adding Filters Filters are the primary way to find experts and narrow results. SkillsDB supports several types of filters that can be combined. ​ Adding a skill or career filter To find people who have a specific skill or who are assigned to a particular career: Select the search input and type a skill or career name. Select the matching skill or career from the suggestion dropdown. SkillsDB adds a filter tag and updates the results to show matching people. You can add multiple skill or career filters. Use the Match all / Match any toggle to control how multiple filters interact (see Matching mode below). ​ Adding an org structure filter Org structure filters let you narrow results by organizational attributes such as department, location, or team. These filters appear as additional dropdowns below the main search input when active. To add an org structure filter: Run a search that returns people results (use People scope or add a skill/career filter). Select the search input and type or scroll to find an org attribute — for example, Department . Select the org attribute from the suggestion dropdown. In the org filter that appears, select one or more values from the dropdown (for example, choose specific department names). Available org structure filters include: Business Unit, Division, Department, Team Country, State, City, Site, Location Shift, Business Region Tip: Combine a skill filter with a department filter to find experts in a specific skill within a particular team or business unit. ​ Adding a certification filter To find employees with a specific certification: Set the scope to Certifications or All . Type a certification name in the search input and select it from the suggestions. SkillsDB returns matching employees alongside certification status information. When the scope is set to Certifications , use the Display menu to toggle between two views: Certifications — shows the certification catalog Employee Certifications — shows individual employees’ certification records, including status and expiration ​ Using Sub-filters Sub-filters refine an individual filter tag with additional criteria. For example, when searching for people with a skill, sub-filters let you require that those people hold an Expert flag for that skill, meet a minimum proficiency grade, or completed training within a specific time period. ​ Adding sub-filters to a skill filter Add a skill as a filter (see Adding a skill filter). Select the filter icon on the skill filter tag. The sub-filters panel opens with the following options: Sub-filter Description Skill Flags Filter by flag designation. Select Expert to find people flagged as experts for this skill. Select Focus to find people who have this skill marked as a focus area. Minimum Grade Filter to people who meet or exceed a specified proficiency level (grade). The available grade values are determined by your organization’s configured grading scale. Training Date Filter by when training was last completed. Options: Last 30 days, Last 90 days, Last 6 months, Last 12 months, Older than 12 months. Select your desired sub-filter values and close the panel. Results update automatically. Note: The Expert flag is assigned by administ --- ## Azure Entra ID SSO Setup URL: https://help.skillsdb.com/identity-and-provisioning/azure-sso-setup Quick Summary: Set up SAML 2.0 Single Sign-On between Microsoft Entra ID and SkillsDB by creating an Entra enterprise application, exchanging SAML endpoint URLs with SkillsDB Support, configuring the required attribute claims ( NameID , firstName , lastName ), and providing your App Federation Metadata URL back to SkillsDB. ​ Overview This guide walks Microsoft Entra ID (Azure AD) administrators through the steps required to integrate SkillsDB with their organization’s identity provider via SAML 2.0 Single Sign-On (SSO). Once configured, users can sign in to SkillsDB using their existing corporate credentials — without a separate SkillsDB password. Setup is a two-way exchange between two parties: SkillsDB Support provides the SAML endpoint URLs (Identifier, Reply URL, and Sign on URL) that the customer must paste into the Entra enterprise application. The customer creates the Entra enterprise application, configures SAML, and returns either the App Federation Metadata URL (preferred) or, if that is not available, an x509 certificate plus the IdP SSO URL and IdP Entity ID. SSO handles authentication only — it confirms who the user is at sign-in time. It does not create, update, or deactivate SkillsDB user accounts. To automate account lifecycle alongside SSO, configure SCIM provisioning as well. Most customers configure both. This guide covers the Microsoft Entra ID setup path. If you use a different identity provider (such as Okta, OneLogin, or Google Workspace), the SAML concepts are the same but the UI steps differ — contact SkillsDB Support for guidance. ​ Prerequisites Before you begin, make sure you have: Permission level : Microsoft Entra administrator access with permission to create enterprise applications Setup requirement : A Tenant URL and Secret Token request initiated with SkillsDB Support — Support will deliver the SAML endpoint URLs in a shared file once the request is processed Access requirement : The Microsoft Entra admin center at Identity > Applications > Enterprise applications ​ How to create the Entra enterprise application 1 Open Enterprise applications in Entra Log in to the Microsoft Entra admin center , navigate to Enterprise applications , and select + New application . 2 Create your own application Select + Create your own application at the top of the application gallery. 3 Name and register the application Enter a name for the application (for example, SkillsDB ), select Integrate any other application you don’t find in the gallery (Non-gallery) , and select Create . 4 Open Single Sign-On setup On the application’s overview page, navigate to Single sign-on and select SAML . The enterprise application is now ready to receive SAML configuration values from SkillsDB. ​ How SkillsDB shares the SAML endpoint URLs SkillsDB Support delivers the SAML endpoint URLs to your IT team in a text file. The file is uploaded to Google Drive and shared with the email addresses you provide; a link is also sent over email. The file contains three URLs in this format: Identifier (Entity ID) & Reply URL (Assertion Consumer Service URL): https://login.skillsdb.com/v1/b2b/sso/callback/{connection_id} Sign on URL: https://login.skillsdb.com/v1/public/sso/start?connection_id={connection_id}&public_token={public_token} Note: Test environments use https://test.stytch.com/* rather than https://login.skillsdb.com/* . SkillsDB Support will send the correct values for your environment. ​ How to configure SAML in the enterprise application With the URLs from SkillsDB Support in hand, configure the Basic SAML Configuration section of your enterprise application. 1 Edit Basic SAML Configuration On the Single sign-on page of your enterprise application, select Edit on the Basic SAML Configuration card. 2 Paste the SkillsDB URLs Paste the values from the SkillsDB-provided file into the corresponding fields: Identifier (Entity ID) — the SkillsDB callback URL Reply URL (Assertion Consumer Service URL) — the same SkillsDB callback URL Sign on URL — the SkillsDB sign-on URL Leave all other fields blank. 3 Save the configuration Select Save . ​ How to configure attributes and claims SkillsDB requires three SAML claims to identify and create users: a unique email identifier ( NameID ), firstName , and lastName . 1 Open Attributes & Claims On the Single sign-on page, select Edit on the Attributes & Claims card. 2 Update the Unique User Identifier Under Required claim , select Unique User Identifier (Name ID) and change the Source attribute to user.primaryauthoritativeemail . 3 Replace the additional claims Under Additional claims , delete the default options and add two claims: Claim name Source attribute firstName user.givenname lastName user.surname Save the changes. These three claims are required. The final claim mapping that SkillsDB stores on its side is: { "email" : "NameID" , "first_name" : "firstName" , "last_name" : "lastName" } ​ Adding optional custom attributes If your organization needs to send additional attributes (for example, Department or JobTitle ), add them in the same Attributes & Claims window: Select + Add new claim Enter a Name for the claim (for example, Department ) Set the Source attribute to the corresponding Entra ID user property Save After adding any custom claims, send the exact claim Names to SkillsDB Support so they can extend the mapping on the SkillsDB side. ​ How to provide identity provider metadata to SkillsDB After SAML is configured, SkillsDB needs your identity provider’s metadata to verify SAML assertions. There are two ways to deliver this — the App Federation Metadata URL is strongly preferred. ​ Option 1: App Federation Metadata URL (preferred) The App Federation Metadata URL is auto-rotating and self-contained. Use this option whenever it is available. 1 Locate the App Federation Metadata URL On the Single sign-on page, scroll to the SAML Certificates section and copy the App Federation Metadata Url . The URL has this shape: https://login.microsoftonlin --- ## Azure Sync Considerations URL: https://help.skillsdb.com/identity-and-provisioning/azure-sync-considerations Quick Summary: When SCIM syncs users from Microsoft Entra ID into SkillsDB, several Entra and Stytch limitations affect how email changes, manager assignments, and group deletions propagate. This page documents each limitation and the workaround. ​ Overview Microsoft Entra ID’s SCIM implementation has documented limitations that customers using SkillsDB should understand before enabling provisioning. This page covers: How email changes propagate for internal vs. external (guest) users The manager provisioning race condition on the first sync and how to resolve it Why manager unassignments in Entra do not propagate When SkillsDB deactivates users automatically How SkillsDB handles groups that are deleted in Entra How SkillsDB prevents circular management hierarchies Each section is independent. Read the ones that apply to your scenario. ​ Prerequisites Before using this page, make sure you have: Setup requirement : An active SCIM connection between Entra and SkillsDB (see SCIM Setup ) Permission level : Microsoft Entra administrator access to diagnose or reconfigure provisioning ​ Provisioning mapping The SCIM Setup guide requires mapping externalId to objectId in the Entra provisioning attributes. If you enabled SCIM without completing this mapping, do it now — the correction applies to future sync events and does not require recreating existing users. ​ Email change behavior Entra handles email changes differently depending on whether the user is internal or external. SkillsDB follows Entra’s behavior. ​ Internal users For users created directly in Entra as user accounts, email changes propagate through SCIM. SkillsDB updates the existing user’s email to match. ​ External users (guests) For users invited to Entra as guests, the invitation email cannot be changed. To change an external user’s email, Entra requires removing the guest and re-adding them with the new email. When this happens: SkillsDB receives a deprovisioning event for the old email and deactivates that user SkillsDB receives a provisioning event for the new email and creates a new user record The two records are independent. Historical data (assessments, training, assignments) on the old record is preserved but does not carry over to the new one. ​ Manager provisioning order On the first-ever SCIM sync, Entra does not guarantee that managers are provisioned before their direct reports. A direct report may be created in SkillsDB before their manager, in which case the manager cannot be assigned on that event. ​ How to resolve this Restart provisioning on the Entra enterprise application after the first sync cycle completes. The restart triggers a full re-sync, which includes manager assignments now that all users exist in SkillsDB. Restart after every initial SCIM configuration, and any time you suspect manager assignments are incomplete. ​ Option 1: Restart manually 1 Open the application In the Azure portal, navigate to Enterprise applications > All applications and select your SCIM application. 2 Go to Provisioning Select Provisioning > Overview . 3 Restart Select Restart provisioning . ​ Option 2: Automate the restart If you want to restart provisioning on a recurring basis, call the Microsoft Graph API. Find your enterprise app’s service principal ID List provisioning jobs to get the job ID: GET /servicePrincipals/{servicePrincipalId}/synchronization/jobs Restart the job: POST https://graph.microsoft.com/v1.0/servicePrincipals/{servicePrincipalId}/synchronization/jobs/{jobId}/restart Content-Type: application/json { "criteria" : { "resetScope" : "Full" } } Schedule the call via Azure Logic Apps, Power Automate, an Azure Automation Runbook, GitHub Actions, or an Azure DevOps pipeline. ​ Manager unassignment Entra does not propagate null attributes through SCIM. If you remove a user’s manager in Entra without assigning a new one, the manager field becomes null and Entra skips it during the next sync. SkillsDB retains the previous manager assignment until a new, non-null manager is provided. Reassigning a user to a different manager works as expected — the new manager value propagates and SkillsDB updates the record. This is an Entra-side limitation, documented in Microsoft’s Entra ID SCIM documentation : Entra ID currently can’t provision null attributes. If an attribute is null on the user object, it will be skipped. ​ Workaround To remove a manager assignment in SkillsDB when the user will not have a new manager in Entra, have a SkillsDB administrator clear the manager field directly in SkillsDB. The change is local to SkillsDB and is not overwritten by future SCIM events (because Entra continues to send null for that attribute). ​ User deactivation SkillsDB soft-deletes a user (sets them inactive without removing their data) when any of the following occurs in Entra: The user is removed from all provisioned SCIM groups The user is disabled in Entra (account enabled set to off) The user is unassigned from the SCIM application Deactivated users remain in SkillsDB for reporting and audit purposes. Their historical assessments, training records, and assignments are preserved. If the same user is later re-provisioned through SCIM, SkillsDB reactivates the existing record rather than creating a new one. ​ Ghost group handling A ghost group is a SCIM group that is deleted in Entra while users are still assigned to it in SkillsDB. SkillsDB handles this automatically: If a user has other active SCIM group memberships, they are removed from the deleted group and their permission level is recalculated based on their remaining groups If the deleted group was the user’s only SCIM group, the user is deactivated (soft-deleted) If the deleted group was a custom SCIM group, any career automations attached to it are cleaned up The two default groups ( SkillsdbGlobalAdmins and SkillsdbFullAccess ) cannot be deleted through SCIM — delete events for these groups are ignored. ​ Circular hierarchy prevention SCIM can transmit manager assig --- ## Identity & Provisioning Overview URL: https://help.skillsdb.com/identity-and-provisioning/overview Quick Summary: SkillsDB separates authentication (who you are — handled by SSO) from provisioning (which user accounts exist and what they can do — handled by SCIM). Most customers configure both so users sign in with their corporate credentials and their accounts stay in sync with the identity provider automatically. ​ Overview SkillsDB integrates with your identity provider (IdP) — such as Microsoft Entra ID (Azure AD), Okta, or OneLogin — through two independent mechanisms: Single Sign-On (SSO) lets users sign in to SkillsDB using their existing corporate credentials. SSO handles authentication at sign-in time only. SCIM (System for Cross-domain Identity Management) keeps SkillsDB user accounts in sync with your IdP automatically. SCIM handles account creation, attribute updates, group membership, and deactivation — everything that happens around the account, outside of sign-in. You can configure SSO without SCIM (users sign in via SSO but their accounts are managed manually in SkillsDB), SCIM without SSO (accounts stay in sync automatically but users sign in with username and password), or both. Most customers configure both. SCIM support in SkillsDB covers: User creation, updates, and deactivation driven by the IdP Group membership mapping to SkillsDB permission levels Manager hierarchy syncing via Entra’s enterprise_extension.manager attribute Automatic career assignment when users are provisioned into specific groups An audit log of every provisioning event for compliance and troubleshooting ​ How the SCIM pipeline works SkillsDB receives SCIM events through Stytch, its authentication and identity platform. This layer handles the SCIM 2.0 protocol and forwards events to SkillsDB as signed webhooks. Identity Provider (Entra, Okta, etc.) │ │ SCIM 2.0 ▼ Stytch │ │ Signed webhook ▼ SkillsDB For customers, this means: Configuration lives in the IdP and in the SkillsDB SSO & SCIM settings page — not in SkillsDB code or APIs SkillsDB does not expose a SCIM endpoint that customers integrate against directly Changes in the IdP appear in SkillsDB within one sync cycle ​ Where to configure SCIM in SkillsDB Navigate to Settings > SSO & SCIM and select Configure SSO and SCIM settings . This page is visible only to administrators. It contains: The Last SCIM sync timestamp Two buttons in the top right: Event Log and Create SCIM Group Two admin-assistance links — Users without a current manager and Users with a manager assigned The Default SCIM Groups table with the two built-in groups The Custom SCIM Groups table listing every custom group your administrators have created or that has been auto-created from IdP events When no SCIM connection is active, the page shows a message prompting you to configure SCIM in your identity provider — the group-management UI is hidden in this state. ​ Disabling username/password login When your organization has an active SSO connection, you can turn off password-based sign-in so users authenticate only through your identity provider. This control appears as the Username/Password Login toggle on the SSO & SCIM settings page, and it is visible only while at least one SSO connection is active. Only administrators can change this setting. Password login is enabled by default, so users can sign in with either their SkillsDB email and password or SSO until an administrator disables it. 1 Open the SSO & SCIM settings page Navigate to Settings > SSO & SCIM and select Configure SSO and SCIM settings . 2 Turn off the toggle Set the Username/Password Login toggle to off. SkillsDB opens a Disable Password Login confirmation dialog that warns “Users without SSO credentials will be unable to sign in.” 3 Confirm the change Select Disable Password Login . SkillsDB confirms with the message “Password login has been disabled. Users will need to use SSO.” When you disable password login, SkillsDB rejects all password-based sign-in attempts immediately, and every user must sign in through SSO from that point on. To restore password sign-in, set the Username/Password Login toggle back on. SkillsDB re-enables it immediately and does not ask for confirmation. Warning: If you disable password login, any user without SSO credentials cannot sign in. Confirm that every active user can authenticate through your identity provider before you turn this off. ​ Related Articles SCIM Setup Step-by-step configuration for Microsoft Entra ID, including the enterprise application, Tenant URL and Secret Token, and attribute mapping. SCIM Groups and Permissions The two default groups, custom SCIM groups, the three permission levels (Admin, Full Access, Basic), and automatic Manager promotion. SCIM Career Automations Automatically assign careers to users when they are provisioned into specific SCIM groups, with configurable scope. SCIM Event Log The audit trail for every provisioning event — filter, export, and troubleshoot sync issues. Azure Sync Considerations Known Entra limitations for email changes, manager assignment, and deactivation, plus workarounds. Sign-in and SSO How Single Sign-On works in SkillsDB, independent of SCIM provisioning. ​ Common Questions Do I need SCIM if I already have SSO configured? No, SSO works independently. Without SCIM, a SkillsDB administrator must create, update, and deactivate user accounts manually. With SCIM, those actions happen automatically based on changes in your identity provider. Does SkillsDB expose a public SCIM endpoint I can integrate with? No. SkillsDB’s SCIM layer runs through Stytch, which handles the SCIM 2.0 protocol on SkillsDB’s behalf. You configure SCIM in your identity provider using the Tenant URL and Secret Token that SkillsDB Support provides — you do not integrate against a SkillsDB-hosted endpoint. Which identity providers are supported? Any IdP that supports SCIM 2.0, including Microsoft Entra ID (Azure AD), Okta, OneLogin, Google Workspace, and others. The SCIM Setup guide covers Entra specifically — contact SkillsDB Support for setup --- ## SCIM Career Automations URL: https://help.skillsdb.com/identity-and-provisioning/scim-career-automations Quick Summary: Attach career automations to a custom SCIM group to automatically assign careers when users appear in that group. Each automation has an eligibility rule (all users, or newly provisioned users only), a re-assignment behavior (only once, or always re-assign), an unassign on removal setting, and a one-time initial activation choice made when you save. ​ Overview Career automations tie SCIM group membership to SkillsDB career assignments. When a user is provisioned into a custom SCIM group that has career automations attached, SkillsDB assigns the configured careers to that user automatically — no manual assignment required. Career automations are useful when: New hires in a specific role should always start with a standardized career (for example, every new FinanceAnalysts SCIM group member gets the “Finance Analyst” career) You want careers to follow group membership — including removing the career when a user leaves the group You manage team membership in your identity provider and want SkillsDB career assignments to follow automatically Career automations are configured per custom SCIM group. The two default groups ( SkillsdbGlobalAdmins and SkillsdbFullAccess ) do not support career automations. SkillsDB never modifies a career a user already holds. If an admin or manager changes the level on an assigned career, SCIM does not reset it. If a career was assigned manually before the automation ran, the automation leaves the career and its level untouched. ​ Prerequisites Before setting up career automations, make sure you have: Permission level : SkillsDB administrator Setup requirement : At least one custom SCIM group (see SCIM Groups and Permissions ) Setup requirement : The careers you want to assign already exist in SkillsDB Access requirement : Settings > SSO & SCIM > Configure SSO and SCIM settings ​ What a career automation contains Each career automation on a custom SCIM group has these fields: Field Required Purpose Career Yes The SkillsDB career to assign to users in this group. Level No The career level to assign. Populated dynamically from the selected career. When you pick a career that has levels, the first level is pre-selected; clear it to assign the career without a level. Re-assignment Yes Only once — exclude users assigned previously assigns the career at most once per user. Always re-assign re-assigns the career whenever it is missing while the user is a member. Eligibility Yes All users (the default) assigns to every eligible group member. Newly provisioned users only assigns only to users whose account was created within the last 30 days, measured at the moment of assignment. Unassign when removed from group No When enabled, the career is automatically unassigned when the user is removed from the group. Initial activation Yes, at save A one-time choice for each new or changed automation: Apply to current and future members , or Activate, but do not apply to current members (the pre-selected default). See The initial activation choice below. A single custom SCIM group can have any number of career automations, but each career can appear in at most one automation per group. Each automation is evaluated independently. ​ How re-assignment works Re-assignment Behavior Best for Only once — exclude users assigned previously The automation assigns its career at most once per user. If an admin later removes the career, SkillsDB does not re-assign it on subsequent syncs, and a user who leaves and rejoins the group is not assigned again. Onboarding defaults. Use when you want to seed a career and let managers change or remove it later without SkillsDB restoring it. Always re-assign Whenever the career is missing while the user is a group member, the next sync re-assigns it. Users who rejoin the group are assigned again. Enforcing a standardized career while the user is in the group. Warning: Always re-assign overrides manual changes: if an admin removes the career from a member, the next SCIM event for that user re-assigns it. The only way to make the removal stick is to remove the user from the group in your identity provider, or change the automation’s re-assignment behavior. SkillsDB never resets a manually changed career level — level edits always stick in both modes. ​ How eligibility works The eligibility rule decides which users the automation applies to: All users : every group member is eligible, regardless of when their account was created. Newly provisioned users only : only users whose SkillsDB account was created within the previous 30 days are eligible, measured at the moment of assignment. How the account was created does not matter, and careers the user already holds do not matter. When a Newly provisioned users only automation skips a user because their account is older than 30 days, the skip is recorded in the SCIM event log as a Career Skipped event. Identity providers such as Entra routinely send “user created” and “user added to group” as separate SCIM events, in varying order. SkillsDB treats a user created and added to the group in separate events identically to one provisioned in a single event. ​ The initial activation choice When you save a new automation — or change an existing automation’s eligibility rule — SkillsDB asks for a one-time activation choice for that automation: Apply to current and future members : the career is immediately assigned to all current group members who meet the eligibility rule, and to eligible future members as they are provisioned. If the group has active members, SkillsDB shows a confirmation with the member count before saving. Activate, but do not apply to current members (the pre-selected default): current members never receive the career from this automation, including on any later sync event. Only users who appear in the group after the save receive it. Each excluded current member is recorded in the SCIM event log as a Career Excluded event. The exclusion also covers members who are deactivated at th --- ## SCIM Event Log URL: https://help.skillsdb.com/identity-and-provisioning/scim-event-log Quick Summary: The SCIM Event Log records every provisioning event SkillsDB receives, including user creation, updates, deactivations, group changes, and career assignments. Use it to verify a sync worked or to diagnose why a user did not appear. ​ Overview The SCIM Event Log is an audit trail for every SCIM event that SkillsDB processes. Each row represents one action triggered by your identity provider, the SCIM background sync, or an administrator. Use the event log to: Verify that a specific user or group change was processed Diagnose why a user is missing, deactivated, or has the wrong permission level Track permission changes and manager reassignments over time Export a filtered audit trail for compliance reporting The event log is admin-only and covers events from your company only. Events from other SkillsDB customers are not visible. ​ Prerequisites Before using the event log, make sure you have: Permission level : SkillsDB administrator Setup requirement : An active SCIM connection (see SCIM Setup ) Access requirement : Settings > SSO & SCIM > Configure SSO and SCIM settings , then select Event Log ​ How to open the event log 1 Open the SSO & SCIM settings Navigate to Settings > SSO & SCIM and select Configure SSO and SCIM settings . 2 Open the Event Log In the top right of the page, select Event Log . The event log page opens with the most recent events first. The event log page has two controls at the top: Export downloads the currently filtered events as an Excel file ( scim_event_log_YYYY-MM-DD.xlsx ) Refresh refetches the event list ​ What each column shows Column What it shows Event Human-readable description of what happened. For updates, shows the old and new values. Type The event type — one of fifteen categories listed in the next section. Shown as a colored badge. Person The user the event affected. Empty for group-only events like Group Created . Group The SCIM group the event relates to. Empty for events that do not involve a group. Source Where the event came from: Webhook , Cron Sync , or Manual . When Event timestamp in MMM d, HH:mm format. Hover to see the full date, day of week, and seconds. ​ Event types The event log has fifteen event types, each representing a specific action. The Event Type filter in the toolbar lets you filter by one or more types simultaneously. Event type What it means Provisioned A new user was created in SkillsDB from a SCIM event. Updated An existing SCIM-provisioned user had their attributes, manager, or group membership updated. Deprovisioned A user was deactivated because they were removed from SCIM, disabled in the IdP, or had all groups removed. User Skipped A SCIM event for a user was received but not acted on — for example, the user’s groups are not registered in SkillsDB. Group Created A new SCIM group was registered in SkillsDB (either default, auto-created from an IdP event, or admin-created). Group Auto-Created A custom SCIM group was automatically registered from an IdP event with the Basic permission level. Group Updated An existing SCIM group was modified (permission level, description, or automations). Group Deleted A custom SCIM group was deleted or deactivated. (Default groups cannot be deleted — see SCIM Groups and Permissions .) Member Added A user was added to a SCIM group. Member Removed A user was removed from a SCIM group. Career Assigned A career automation ran and assigned a career to a user. See SCIM Career Automations . Career Removed A career automation unassigned a career because the user was removed from the group and the automation has unassign-on-removal enabled. Career Excluded A current group member was excluded from a career automation saved with “Activate, but do not apply to current members”. Career Skipped A “Newly provisioned users only” automation skipped a user because their account is older than 30 days. Permission A user’s effective SkillsDB permission level changed (for example, Basic → Admin). ​ Event sources The Source column shows where the event originated: Webhook — The event came from your identity provider through Stytch. This is the most common source for real-time provisioning activity. Cron Sync — The event came from SkillsDB’s scheduled background sync. This sync retries manager assignments that failed during the initial provisioning and periodically reconciles group memberships. Manual — The event was triggered by a SkillsDB administrator action, such as creating or editing a custom SCIM group. ​ How to filter events The toolbar above the event table supports four filter types. Filters can be combined. Filter Options Event Type Multi-select from the fifteen event types listed above. Source Select one of Webhook , Cron Sync , or Manual . Group Select a specific SCIM group. Populated dynamically from groups that appear in the log. Date Preset range: Today , Yesterday , Last 7 days , Last 30 days , or This month . Filters update the table immediately. Use Export to download the currently filtered results as an Excel file. ​ How to diagnose a provisioning problem The event log is the fastest way to find out why a user is missing or has the wrong state. Use these patterns as starting points: ​ Problem: A user who should be in SkillsDB is missing 1 Filter by Event Type: Provisioned Set the Event Type filter to Provisioned and set a Date range covering when the user was added in your identity provider. 2 Look for the user If you see a Provisioned event for the user, SCIM created them successfully — check whether they were subsequently deprovisioned. If no Provisioned event appears, the SCIM event for that user never reached SkillsDB. 3 Check your identity provider In Entra, verify the user is assigned to the SCIM application and belongs to at least one of the provisioning groups. Use Provision on Demand in Entra to push the user immediately. See SCIM Setup and Azure Sync Considerations . ​ Problem: A user has the wrong permission level 1 Filter by Event Type: Permission and the user Se --- ## SCIM Groups and Permissions URL: https://help.skillsdb.com/identity-and-provisioning/scim-groups-and-permissions Quick Summary: SkillsDB has two default SCIM groups that grant Admin or Full Access permissions, plus administrator-managed custom SCIM groups that can be set to Admin, Full Access, or Basic. A Basic user with direct reports is automatically promoted to Manager. ​ Overview SCIM groups are how SkillsDB determines what a provisioned user can do. When a SCIM event arrives from your identity provider, SkillsDB looks at the user’s current group memberships and sets their SkillsDB permission level based on the highest-privilege group they belong to. There are two kinds of SCIM groups: Default SCIM groups — two built-in groups ( SkillsdbGlobalAdmins and SkillsdbFullAccess ) that administrators cannot delete. These grant Admin and Full Access respectively. Custom SCIM groups — any other group provisioned from your identity provider. These are either auto-created when the first member is provisioned, or created manually by a SkillsDB administrator. Each custom group has a configurable permission level and can trigger automatic career assignment. SkillsDB has three permission levels: Admin , Full Access , and Basic . A fourth role, Manager , is not set by SCIM groups directly — SkillsDB assigns it automatically to Basic users who have direct reports. ​ Prerequisites Before managing SCIM groups, make sure you have: Permission level : SkillsDB administrator Setup requirement : An active SCIM connection (see SCIM Setup ) Access requirement : Settings > SSO & SCIM > Configure SSO and SCIM settings ​ Default SCIM groups SkillsDB ships with two default SCIM groups. Create groups in your identity provider with exactly these names — any user added to one of them receives the corresponding SkillsDB permission level on the next sync. Identity provider group name SkillsDB permission level What the user can do SkillsdbGlobalAdmins Admin Full system access, including configuration, libraries, and user management. SkillsdbFullAccess Full Access Access to all people, skills, training, and reports across the company. No configuration access. Default groups cannot be deleted through SCIM — SkillsDB ignores delete events for them and preserves existing memberships. If a default group does not exist when the first user is provisioned, SkillsDB creates it automatically. To see the current membership counts for each default group, navigate to Settings > SSO & SCIM > Configure SSO and SCIM settings and look at the Default SCIM Groups table. The Active Users column links to a filtered People list showing every user in that group. ​ Custom SCIM groups Any SCIM group you provision from your identity provider that is not one of the two default groups is treated as a custom SCIM group. Custom groups are useful when: You want to grant Full Access or Admin through a group name that matches your organization’s naming conventions You want to assign careers automatically when users join a specific group (see SCIM Career Automations ) You want to deactivate provisioning for a specific group without removing it from your identity provider Custom groups are created in one of two ways: Auto-created : When a user is provisioned with membership in a group that does not yet exist in SkillsDB, the group is auto-created with Basic permission and no career automations. An administrator can upgrade it later. Manually created : An administrator creates the group in SkillsDB before provisioning users into it. This is the right approach when you want to set the permission level and career automations before the first user arrives. ​ How permission levels resolve when a user belongs to multiple groups A user’s effective SkillsDB permission level is the highest among their active SCIM group memberships, evaluated in this order: If the user belongs to any active group with permission Admin , they receive Admin Otherwise, if the user belongs to any active group with permission Full Access , they receive Full Access Otherwise, the user receives Basic Basic users who have direct reports assigned to them are automatically promoted to Manager If a user is removed from all SCIM groups, SkillsDB deactivates them through the resulting member-removal events from your identity provider. See Azure Sync Considerations for the full deactivation behavior. ​ How to create a custom SCIM group 1 Open the SSO & SCIM settings Navigate to Settings > SSO & SCIM and select Configure SSO and SCIM settings . 2 Open the Create SCIM Group modal In the top right of the page, select Create SCIM Group . 3 Enter the group details Enter a Group Name that exactly matches the group name in your identity provider. Group names must be 100 characters or fewer and may only contain letters, numbers, dots, hyphens, and underscores. The group name cannot be changed after the group is created. Optionally enter an Internal Description to help other administrators understand the group’s purpose. This description is only visible to SkillsDB administrators — it is not synced to the identity provider. 4 Select the permission level Choose one of Admin , Full Access , or Basic from the Permission Level dropdown. Warning: Selecting Admin grants full system access, including the ability to modify company configuration. Only use this for groups that should hold administrator rights. 5 Optionally add career automations In the Career Automations section, select + Add Career Automation to attach one or more careers that should be automatically assigned when users are provisioned into this group. See SCIM Career Automations for how to configure these. 6 Create the group Select Create . The new group appears in the Custom SCIM Groups table. Once the group exists in SkillsDB, users provisioned into the matching identity-provider group receive the configured permission level on their next sync. ​ How to edit a custom SCIM group Select the edit icon in the Action column of the Custom SCIM Groups table. The edit modal lets you change the description, permission level, and career automations. The group na --- ## SCIM Setup URL: https://help.skillsdb.com/identity-and-provisioning/scim-setup Quick Summary: Set up SCIM provisioning between Microsoft Entra ID and SkillsDB by creating an Entra enterprise application, connecting it with the Tenant URL and Secret Token from SkillsDB, and mapping the required attributes. ​ Overview SCIM provisioning automatically creates, updates, and deactivates SkillsDB user accounts based on changes in your identity provider (IdP). SkillsDB supports SCIM through Stytch, which receives SCIM events from your IdP and forwards them to SkillsDB as webhooks. This guide covers the Microsoft Entra ID (Azure AD) setup path. If you use a different IdP, the concepts are the same but the UI steps differ — contact SkillsDB Support for guidance. SCIM provisioning handles: Creating SkillsDB users when they are added to the SCIM application in Entra Updating user attributes (name, manager, contact information) when they change in Entra Assigning SkillsDB permission levels based on SCIM group membership Deactivating SkillsDB users when they are removed from the SCIM application or disabled in Entra SCIM does not replace Single Sign-On (SSO). SSO authenticates users at sign-in; SCIM provisions their accounts. Most customers configure both. ​ Prerequisites Before you begin, make sure you have: Permission level : Microsoft Entra administrator access Setup requirement : A Tenant URL and Secret Token from SkillsDB Support Access requirement : The Entra admin center at Identity > Applications > Enterprise applications ​ How to enable SCIM provisioning 1 Create the Entra enterprise application Log into the Microsoft Entra admin center , navigate to Enterprise applications , and select to create a new application. Select Create your own application at the top. Name the application, select Integrate any other application you don’t find in the gallery (Non-gallery) , and select Create . 2 Open the provisioning configuration On the new application’s overview page, select Provisioning from the left sidebar, or select Provision User Accounts under the Getting Started section. Under Get Started > Create Configuration , select Connect your application . Choose Automatic from the dropdown. 3 Provide the SkillsDB credentials Under New provisioning configuration , get the Tenant URL and Secret Token from SkillsDB Support and add them to the corresponding fields, then select Test Connection . Warning: Do not share the Secret Token. Anyone with this token can provision users into your SkillsDB instance. 4 Map the externalId attribute SCIM uses a stable external identifier to track users across systems. You must map Entra’s objectId to the SCIM externalId attribute. On the left sidebar, under Manage , select Provisioning Select Provision Microsoft Entra ID Users In the customappsso Attributes table, locate the externalId record Update the Source Attribute to objectId Select OK and Save 5 Turn on provisioning Back on the Provisioning page, turn Provisioning Status to On . 6 Provision users Test the SCIM integration by assigning or removing people from the application and watching the changes propagate to your Stytch member records. Entra syncs automatically on a 40-minute timer; use Provision on Demand to speed up testing. Once provisioning is on, Entra sends user and group changes to Stytch, which forwards them to SkillsDB. Changes appear in SkillsDB within one sync cycle. ​ How SkillsDB maps SCIM groups to permission levels SkillsDB recognizes two default SCIM groups. Add users to these groups in Entra to grant the corresponding permission level in SkillsDB: Entra group name SkillsDB permission level SkillsdbGlobalAdmins Admin SkillsdbFullAccess Full Access Users who are not in either default group receive the Basic permission level. Basic users with direct reports are automatically promoted to the Manager role. Any other SCIM group you provision is auto-created in SkillsDB as a custom SCIM group with Basic permission. Administrators can upgrade these custom groups to Full Access or Admin, and attach career automations to them. See SCIM Groups and Permissions for the complete model. ​ SCIM attribute mapping When a SCIM event provisions or updates a user, SkillsDB maps the SCIM payload from your identity provider in three ways: Direct fields are stored on the user’s SkillsDB record itself. Org schema attachments are stored as company-level entities (Job Title, Country, City, Department, Division) and linked to the user. SkillsDB creates the entry under your company automatically the first time a value appears in a SCIM event. Identity tracking fields are set on the user record so SkillsDB knows the user came from SCIM and can be reconciled with Stytch on every subsequent event. Group membership (the groups array) drives the user’s permission level rather than mapping to a single field. See SCIM Groups and Permissions for the full resolution rules. ​ Direct fields SCIM attribute SkillsDB field Notes email_address Email Address Must be unique across the SkillsDB instance. Duplicates are rejected. name.given_name First Name Falls back to the first portion of display_name if given_name is not provided. name.family_name Last Name Falls back to the remainder of display_name , then to a value derived from the email, then to Missing . display_name First/Last Name (fallback) Used only when given_name or family_name is missing. active Active status Boolean. When false , SkillsDB deactivates the user. addresses[0].street_address Address Only the first address in the array is used. addresses[0].region State/Province Only the first address in the array is used. addresses[0].postal_code Zip/Postal Code Only the first address in the array is used. phone_numbers[type=work] Business Phone The first entry with type set to work . phone_numbers[type=mobile] Mobile Phone The first entry with type set to mobile . phone_numbers[type=fax] Fax Number The first entry with type set to fax . enterprise_extension.manager.value Manager Resolves the manager by their SCIM member ID. If the manager is not yet in S --- ## Welcome to SkillsDB URL: https://help.skillsdb.com ​ Welcome! 👋 SkillsDB is your organization’s skills intelligence and analytics platform. It helps you track your skills, complete assessments, find training opportunities, and plan your career growth — all in one place. This guide will help you get up and running quickly. ​ Getting Started 1 Sign In & Set Up Your Profile After receiving your login credentials, sign in and complete your profile. Add your current role, department, and any skills you already have. 2 Complete Your Skills Self-Assessment Your organization may have a self-assessment ready for you. Rate your proficiency across the skills relevant to your role — this helps identify strengths and growth areas. 3 Explore Your Skills Profile Visit your skills profile to see your skill levels, gaps, and recommendations. This is your personal dashboard for growth. 4 Browse Training & Certifications Discover training courses and certifications that can help you close skill gaps and advance your career. 5 Set Career Goals Use the Careers feature to explore career paths within your organization and see what skills you need to get there. ​ Key Features for You Your Skills Profile View and manage your skills, complete self-assessments, and track your progress over time. Training & Learning Find training courses and learning plans assigned to you or available across your organization. Certifications Track your certifications, upload proof of completion, and stay on top of expiration dates. Career Paths Explore career opportunities and see exactly which skills you need to reach your next role. ​ Helpful Resources Core Concepts Learn about proficiency levels, skill gaps, the skills matrix, and how everything connects. Search Your Org Search and browse skills, careers, certifications, training, and experts across your organization. Tutorials Common workflows like completing assessments, finding training, etc. Glossary Definitions for the terms used throughout SkillsDB and this help center. ​ What You Can Do with SkillsDB Track skills across your organization — Define skills libraries, assign them to people, and monitor proficiency levels Run assessments — Self-assessments for individuals and manager assessments for team leads, with configurable grading scales Manage certifications — Track certificate lifecycles, expirations, and required renewals Build learning plans — Create and assign learning resources to help people grow their skills Analyze skill gaps — Identify where your teams need development and plan upskilling initiatives Manage training — Track training activities, approve training requests, and monitor training expirations across your teams Conduct surveys — Create and distribute surveys to collect feedback from your workforce Explore your organization — Search for experts, browse skills and careers, and find training resources Upload and manage files — Store documents, certificates, and other files on your profile for easy access and sharing Generate reports — Skills matrices, training matrices, analytics dashboards, and exportable data ​ Who Uses SkillsDB Role What They Do Users Manage their skills profile, complete self-assessments, build learning plans, upload certifications, respond to surveys, upload files Managers View their team, run assessments, analyze skills and training, track certifications, approve promotions Administrators Configure the platform, manage libraries, set up careers, create surveys, import/export data ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Careers URL: https://help.skillsdb.com/libraries/careers Quick Summary: The Careers library is where administrators build and manage every job role in the organization. Each career holds a structured set of skills, organized into sections and levels, with configurable settings for proficiency grading, training tracking, and assessments. ​ Overview Careers in SkillsDB are the organizational templates that define what skills matter for a given job role. Each career represents a position or role — such as “Software Engineer” or “Operations Manager” — and contains a curated set of skills that employees in that role are expected to develop and demonstrate. Careers serve as the foundation for SkillsDB’s skills tracking, assessment, and analytics features. When a person is assigned to a career, they receive a skills profile aligned to that role. Their proficiency grades are tracked against the career’s benchmarks, and their training completion is measured against the career’s training requirements. All of this data flows into the Skills Matrix, assessments, and team analytics. A career is more than a flat list of skills. It has a three-level hierarchy: the career itself contains sections that group related skills together, and levels that represent progression stages within the role (for example, Level 1 through Level 5). Skills can be assigned individual benchmarks at each level, so the expected proficiency for a given skill shifts as employees advance. Administrators have full access to create, edit, configure, and delete careers. Managers can view careers and assign their team members to them. Standard employees can view the career they are assigned to and track their own progress against its requirements. The Careers library requires the Library Roles setting to be enabled in your organization settings. If the Careers section is not visible in your sidebar, contact your SkillsDB administrator to confirm the setting is active. ​ Prerequisites Before working with careers, you need: Permission level : Administrator role to create, edit, configure, or delete careers; Manager role to assign people to careers Setup requirement : Library Roles enabled in your organization settings Optional : Skills created in the Skills library before building out a career (you can also create new skills directly within a career) ​ Understanding Career Structure Every career in SkillsDB follows a consistent three-level hierarchy: Level What it is Example Career The top-level job role or position ”Software Engineer” Section A group of related skills within the career ”Backend Development”, “Security” Skill An individual competency within a section ”Python”, “SQL”, “API Design” Levels are an optional fourth dimension that sit across the entire career. A career can have multiple levels representing seniority tiers (for example, Level 1 through Level 5, or Junior through Principal). When levels are configured, each skill can have a different benchmark grade required at each level — so a Level 1 engineer may need a grade of 2 in Python while a Level 4 engineer is expected to reach a grade of 4. People are assigned to a career and, optionally, to a specific level within it. Their assigned level determines which benchmark grades apply to them, enabling accurate skills gap analysis. Note: Levels, sections, and skills are all optional. A career can be as simple as a name and a flat list of skills, or as structured as a multi-level framework with sections and per-level benchmarks. ​ Navigating the Careers Library To access the Careers library, select Library > Careers from the left sidebar. ​ Group By The library supports three grouping modes via the toggle at the top of the page: Mode Behavior Default A flat list with no grouping. This is the default view. Alphabetical Careers grouped into collapsible sections by first letter. Type Careers grouped by their career type. ​ Columns Column Description Career The career name. Select a row to open the career detail page. Labels Tags applied to the career. Labels can be edited inline using the Add label button. Type The career type (e.g., Job Role). Assigned The number of people assigned to the career. Select Display on the right side of the toolbar to show or hide columns. An additional Letter column is available but hidden by default. ​ Filters Select Filter in the toolbar to open the filter menu. Available filters: Career, Type, Labels, People Assigned. ​ Creating a Career Administrators can create new careers from the Careers library. Each career requires a title and a type. Navigate to Library > Careers Select + Add Career in the top-right navigation area Enter the career name. Under Additional Information , optionally add a Description and Labels Optionally enable Create more to add multiple careers in sequence Select Continue , then choose a career type to create the career. If the type does not exist, use Create career type The new career is created and appears in the careers table. Select the career row to open its detail page and begin building out its structure. To update an existing career, open it from Library > Careers and select Edit career . The dialog prepopulates the name, description, career type, and labels. Update the fields and select Save changes . ​ Building out a Career After creating a career, you structure it by adding levels, sections, and skills. Open a career’s detail page by selecting it from the Library > Careers table. The detail page title displays as Manage / [Career Name] . The detail page shows the career’s sections, the skills within each section, and any associated learning resources. ​ Managing levels Levels define the seniority or progression tiers within a career. Add levels before assigning benchmarks to skills, as benchmarks are tied to specific levels. To manage levels on a career detail page: Select the Levels control within the career structure panel Select + Add Level to create a new level, then enter a Level Title Select Save To reorder levels, drag a level row using its drag handle. The --- ## Certifications URL: https://help.skillsdb.com/libraries/certifications Quick Summary: The Certifications Library is where administrators define, organize, and manage your organization’s certification catalog. From here you can create certification records, assign them to employees, review submission proof, and track completion and expiration status across the whole organization. ​ Overview The Certifications Library is the administrative hub for all certifications in SkillsDB. Administrators build the library by creating certification records — defining the name, issuing authority, type, and other metadata for each certification the organization tracks. Once a certification exists in the library, administrators and managers can assign it to employees, who then submit their proof of completion. That proof flows into an approval workflow where a manager or administrator reviews and approves or rejects the submission. SkillsDB handles the full certification lifecycle from the library: assignment, submission, approval, expiration tracking, and renewal. Every approved submission is stored with a full history, so administrators have an auditable record of who holds which certifications, when they were earned, and when they expire. Administrators have full access to the library — they can create, edit, and delete certification records and manage certification types. Managers can assign certifications to their direct reports and approve their team’s submissions, but cannot create or modify certification definitions. Employees interact with certifications from their own profile and cannot access the library. ​ Prerequisites Before using the Certifications Library, you need: Permission level : Administrator role Access : Navigate to Library > Certifications Note: The Certifications Library is only visible in the sidebar for administrators. Employees see their personal certifications at Profile > Certifications , and managers see their team’s certifications at Team > Certifications . ​ Managing Certification Types Certification types are the categories used to organize your certification catalog — for example, Compliance , Technical , Safety , Leadership , or Vendor . Defining types before building the library makes it easier to filter and report on certifications later. To manage certification types: Navigate to Library > Certifications Select Manage Types in the top navigation bar The Manage Types drawer opens, showing all existing types in order From the drawer you can: Add a type — enter a name and select Save Edit a type — select the edit icon next to any type and update the name Delete a type — select the delete icon; any certifications using that type will have their type field cleared Reorder types — drag types into the preferred display order using the drag handle Types appear in the Type dropdown when creating or editing a certification, and as a filter in the certifications table. ​ Building the Certifications Library ​ Creating a certification To add a new certification to the library: Navigate to Library > Certifications Select + Certification in the top navigation bar Enter the certification name and optionally complete Additional Information : Field Required Notes Name Yes Up to 100 characters. This is the name employees see when assigned the certification. Description No Explain what the certification covers or any prerequisites. Issued by No The issuing authority or organization, such as AWS or PMI. Labels No Select labels to organize the certification. Select Continue , then choose a certification type to create the certification. A type is required; use Create certification type if you need a new one. Expiration dates and proof attachments belong to individual submissions. They are not fields in the library’s create or edit dialog. The certification appears immediately in the library table and is ready to be assigned to employees. ​ Editing a certification Navigate to Library > Certifications Select the certification row to open the detail page Select Actions > Edit . The dialog prepopulates the name, description, type, issuing authority, and labels Update the fields and select Save changes Reopening Edit shows your latest saved values. To remove a description or issuing authority, clear the field and save. To remove the type, choose Select type ; remove selected labels to clear them. If saving fails, the dialog keeps your draft so you can retry. Changes to the certification name and metadata are reflected immediately across all assignment records. Editing a certification does not affect the submission status of employees who have already been assigned it. ​ Deleting a certification Navigate to Library > Certifications Select the certification row and access the delete option from the detail page or row actions Confirm the deletion in the dialog that appears Warning: Deleting a certification removes it from the library and from all employees it has been assigned to. All submission and approval history for that certification is also removed. This action cannot be undone. Consider whether you simply want to stop assigning the certification rather than deleting it entirely. ​ Assigning Certifications to Employees Certifications must be assigned to employees before they can submit proof of completion. Assigning a certification creates an Assigned record on the employee’s profile and triggers a notification prompting them to submit their details. ​ Assigning from the library Navigate to Library > Certifications Locate the certification you want to assign In the People (#) column, select the people count to open the assignment panel The assignment panel opens, showing a searchable list of all employees Search for employees by name using the Search people… field Select Assign next to each person you want to assign the certification to The employee immediately appears in the certification’s detail view with a status of Assigned . ​ Assigning from the certification detail page Selecting a certification’s name in the library opens its detail page, which shows --- ## Skills URL: https://help.skillsdb.com/libraries/skills Quick Summary: The Skills Library is your organization’s master catalog of skills. Administrators can add and manage skills, assign them to people, and analyze proficiency across the organization. Employees can browse the library to discover and add skills to their own profile. ​ Overview The Skills Library is the centralized catalog that holds every skill available in your SkillsDB environment. It serves as the authoritative source for all skills used in assessments, career profiles, learning plans, and skills matrices across your organization. Every skill in SkillsDB originates from the Skills Library. When a skill is added to the library, it becomes available for assignment to individuals, inclusion in careers, and use in assessments. Skills in the library can be tagged with labels for organization, enriched with learning resources, and analyzed for proficiency trends across your workforce. The Skills Library is primarily an administrative tool, but it is also a discovery resource for employees. Employees can browse the catalog, filter by labels, and add skills to their own profile directly from the library view. Who uses the Skills Library: Administrators build and maintain the library — creating skills, assigning people, managing labels, and exporting data. Managers use the library to view and manage skill assignments for their team members. Employees browse the library to explore available skills and add relevant ones to their own skills profile. ​ Navigating the Skills Library To access the Skills Library, select Library > Skills from the left sidebar. ​ Group By The library supports four grouping modes via the toggle at the top of the page: Mode Behavior Alphabetical Default. Skills are sorted alphabetically and grouped into collapsible sections labeled A through Z. Each section header shows the count of skills. Label Skills are grouped by the labels applied to them. By Career Skills are grouped by the careers they belong to. None A flat list with no grouping. ​ Columns Column Description Name The skill name. Select the column header to sort ascending or descending. Select a skill row to open the skill detail page. Description The skill’s description text. Labels Tags applied to the skill for organization and filtering. Labels can be edited inline directly from this column. Experts (#) The number of people designated as experts for this skill. Training (#) The number of learning resources linked to this skill. People (#) The number of people assigned to this skill. Select the count to open the assignment drawer. Actions Row-level action icons for managing the skill. ​ Filters Select Filter in the toolbar to open the filter menu. Available filters: Name — Filter by skill name (is, is not, contains, does not contain). Description — Filter by description text. Labels — Filter by label values. Experts (#) — Filter by expert count (is, is not, above, below). Training (#) — Filter by training resource count. People (#) — Filter by assigned people count. ​ Adding a Skill Administrators can add new skills to the library at any time. Adding a skill makes it immediately available for assignment, career inclusion, and assessment throughout SkillsDB. Navigate to Library > Skills . Select + Skill in the top navigation bar. In the Create skill dialog, enter a Name for the skill. The name field is required. Under Additional Information , optionally enter a Description and select Labels . Select Create skill . Enable Create more first if you want to add another skill. When the skill is added successfully, a confirmation message appears and the new skill populates in the correct alphabetical section of the library. Training, benchmark, expiration, and evidence requirements are configured for a skill within a career. See Adding skills to a career . Tip: Use clear, specific skill names that match the terminology your organization already uses. Consistent naming makes skills easier to find in assessments, careers, and the skills matrix. ​ Editing a Skill Administrators can update a skill’s name, description, or labels after it has been created. Editing a skill updates its details everywhere it appears in SkillsDB — including careers, assessments, and learning plans. Navigate to Library > Skills . Select the skill row you want to edit. On the skill detail page, access the edit option for the skill. The Edit skill dialog opens with the saved name, description, and labels selected. Update the fields as needed. Select Save changes . The skill is updated and the confirmation message “Skill updated successfully” appears. Important: Renaming a skill updates the display name across all areas of SkillsDB, including assessments, career profiles, and reports. Ensure the new name does not create confusion with existing skills before saving. ​ Organizing Skills with Labels Labels are tags you apply to skills to categorize and organize your library. Applying labels makes it easier for administrators, managers, and employees to filter and find relevant skills. Labels can be edited inline directly in the Skills Library table without opening a separate edit modal: Navigate to Library > Skills . In the Labels column, select the label area on the row of the skill you want to tag. Add or remove labels using the label selector that appears. Changes save automatically. To filter skills by label, select the Labels filter in the filter bar and choose one or more label values. Note: Labels are created and managed separately from the Skills Library. To create new labels or manage existing ones, navigate to Company > Settings > Labels . For a full guide, see Labels. ​ Assigning Skills to Team Members Administrators and managers can assign skills directly to people from the Skills Library. When a skill is assigned to a person, it appears on their skills profile and becomes eligible for assessment and grading. ​ Opening the assign drawer Navigate to Library > Skills . In the People (#) column, select the people count for the sk --- ## Training URL: https://help.skillsdb.com/libraries/training Quick Summary: The Training Library is a centralized catalog of learning resources available to your organization. Admins build and curate the library, link resources to skills and careers, and assign them to employees. Employees can suggest new resources for admin review. ​ Overview The Training Library gives administrators a single place to manage all training resources available in your organization. Each resource can be linked to specific skills and careers, assigned directly to employees, and tracked through completion. Resources in the library appear in employees’ Learning Plans when assigned, and employees can suggest new resources for admin approval. Who can use this feature: Role Capabilities Admin Add, edit, delete, and assign training resources; review employee suggestions; export; configure settings Manager View training library; assign training to direct reports (if permitted) Employee View assigned training; suggest new resources The Training Library requires the Library: Training feature to be enabled for your organization. Contact your account manager if it is not visible. ​ Navigating the Training Library Navigate to Library > Training in the left sidebar to open the Training Library. ​ Group By The library supports three grouping modes via the toggle at the top of the page: Mode Behavior Alphabetical Default. Resources grouped into collapsible sections by first letter, with counts per group. Label Resources grouped by the labels applied to them. None A flat list with no grouping. ​ Columns Column Description Name The title of the training resource. Select a row to open its detail page. Labels Any labels applied to the resource. Labels can be edited inline. People (#) The number of people assigned to this training resource. Avg Rating The average rating from employees. Actions Row-level action icons for managing the resource. Select Display on the right side of the toolbar to show or hide columns. ​ Filters Select Filter in the toolbar to open the filter menu. Available filters: Name, Labels, People (#), Avg Rating, Cost, Duration, Provider, Format, Audience. ​ Adding a Training Resource Admins can add training resources directly to the library. Newly added resources are immediately available for assignment. Navigate to Library > Training . Select + Training in the top-right corner. Enter the training title and complete the optional settings described below. Select Continue , then choose a category to create the training. If needed, use Create category to add a category. The new resource appears in the library table immediately after saving. ​ Training Form Field Reference The create and edit dialogs share four settings sections. The title is required. Creation asks for a category after Continue ; editing shows the saved category under Training Details . ​ Additional Information Field Required Details Description No A text description of the resource ​ Training Details Field Required Details Category Yes The training category; select from your configured categories Training URL No Link to the external resource; enter the domain (e.g., coursera.org/course-name ) — https:// is added automatically Cost No Cost in USD from 0 to 99,999 Duration No Estimated duration in Minutes, Hours, Days, or Weeks; the total must be between 0 and 9,999 hours Reference ID No An internal reference code for tracking purposes ​ Training Attributes Field Required Details Provider No The training provider (e.g., Coursera, LinkedIn Learning); select from configured providers Format No The format of the training (e.g., Online, In-Person, Blended); select from configured formats Audience No The intended audience level; select from configured audiences Course level No The difficulty level (e.g., Beginner, Intermediate, Advanced); select from configured levels Labels No Organizational labels to categorize the resource; visible to admins only ​ Related Entities Field Required Details Related skills No Link this resource to one or more skills; it will appear under those skills in the By Skill view Related careers No Link this resource to one or more careers; it will appear under those careers in the By Career view Linking a training resource to skills and careers helps employees discover it through their career profiles and learning paths. Resources linked to a career appear in that career’s detail page. ​ Viewing a Training Record Select any resource in the library table to open its detail page. The detail page includes: Hero section — Title, description, type badge, and status badge Quick stats bar — Duration, Cost, and Provider at a glance Training Details card — Category, Training Format, Target Audience, Course Level, and Reference ID Related Entities card — Skills and careers this resource is linked to, displayed as chips Labels card — Labels applied to the resource (admin view) Training Link card — The external URL with an Open Training button To edit a resource, open it from Library > Training , then select Actions > Edit . The dialog prepopulates the title, category, settings, labels, and related skills and careers. Update the fields and select Save changes . Clearing an optional field or removing a selection also saves that removal. ​ Deleting a Training Resource To delete a resource, select Delete from the row actions in the library table. If the resource is linked to skills or careers, a confirmation dialog will display the number of related entities before proceeding. Deletion is a soft delete — the record is removed from active views but retained in historical data. Before deleting: Employees who have this resource in their Learning Plan will lose access to it. Review the # Assigned , # In Progress , and # Completed counts before deleting an active resource. ​ Assigning Training to People Admins and managers can assign training resources directly to employees from the library. In the library table, select the people count in the People (#) column on the resource row, or open the resource d --- ## Analyze Skills URL: https://help.skillsdb.com/manager-guide/analyze-skills Quick Summary: The My Team Skills page gives managers a career-by-career view of their team’s skills. Drill into any career to see proficiency statistics, open the Skills Matrix to compare individual grades against benchmarks, and export the data to Excel for deeper analysis. ​ Overview The My Team Skills page is the starting point for analyzing your team’s skill proficiency in SkillsDB. It organizes your team’s data by career path, giving you a high-level view of how many people are assigned to each career and how many skills are attached to each path. From this view you can drill into any career to access the Career Overview — a dashboard of proficiency statistics and visualizations for that career — and then into the Skills Matrix , where you can see every person’s grade for every skill side by side, compare against benchmarks, and identify gaps at a glance. Only managers and administrators can access My Team Skills. Employees see only their own profile and cannot access team-level skill data. ​ Navigating to My Team Skills To open the team skills view: Select Skills from the Team section of the left sidebar. The My Team Skills page lists assigned careers in a table grouped by career type (for example, “Job Role”). Two scope chips at the top control which people are included: View What it shows Direct Reports Careers assigned to your immediate direct reports only My Org Careers across your full reporting organization, including indirect reports Select Direct Reports , My Org , both, or neither. Selected chips stay highlighted; select a chip again to turn it off. With neither selected, the page shows all data your permissions allow. My Org already includes direct reports, so selecting both shows the same people as My Org without duplicates. There is no separate All chip. ​ Understanding the team skills table The main table on My Team Skills has the following columns: Column What it shows Name Career or role name Labels Any labels applied to this career in SkillsDB Assigned Number of team members assigned to this career path Skills Number of skills attached to this career You can sort the table by any column. Select a column header to sort ascending; select it again to sort descending. ​ Exploring a Career Selecting a career name in the table opens the Career Overview page for that career. This page provides a statistical summary of how your team is performing across all skills in that career. Summary statistics Seven statistics appear at the top of the Career Overview: Stat What it means Total People Number of team members in this career group Total Assign Number of people with skills assigned from this career Total Skills Number of skills in this career path Meets Target Percentage of people who meet or exceed the benchmark grade Below Target Percentage of people whose grades fall below benchmark Training Resources Number of learning resources linked to skills in this career Skills w/ Training Number of skills in this career that have at least one training resource Charts and visualizations Below the statistics, the Career Overview displays proficiency visualizations including heatmaps, comparative bar charts, donut charts, and skill distribution breakdowns by person and skill. These give you a quick pattern-level view of where your team is strong and where gaps are concentrated. Top and bottom performers The Career Overview also shows: Top performers — Team members with the highest average grade in this career Bottom performers — Team members with the lowest average grade, indicating where targeted support may be needed Select a person’s name to navigate directly to their individual profile. ​ Opening the Skills Matrix The Skills Matrix is the detailed grid view where you can see every team member’s grade for every skill in a career, compared against the benchmark. To open the Skills Matrix from the Career Overview select the Total Assign stat card, or navigate directly from the breadcrumb. The Skills Matrix opens showing a grid with team members as rows and skills as columns. ​ Reading Grade indicators Each cell in the Skills Matrix shows a grade badge that communicates both the raw grade and how it compares to the benchmark for that skill. Indicator Color Meaning Up arrow Blue Grade exceeds the benchmark Star Green Grade exactly meets the benchmark Down arrow Red Grade falls below the benchmark Circle (no grade) Gray No grade has been recorded for this skill The badge also displays the numeric grade value and the difference from the benchmark — for example, +1 means one grade point above benchmark, and -2 means two points below. Note: The grading scale labels (such as “Beginner” through “Expert”) are configured by your organization’s administrator. The exact values shown depend on your account’s grading scale settings. ​ Switching Views The Skills Matrix page offers six different views, selectable from the view bar in the breadcrumb area. Each view presents your team’s skills data through a different lens. View What it shows Skills Matrix Grid of team members x skills with grade badges and benchmark indicators Training Matrix Grid view focused on training completion status for each skill Skills Flag Grid view showing flag indicators (Expert, Mentor, Focus, Interest) per person per skill Nightingale Circular “rose” chart showing proficiency distribution across skills Bar Chart Bar chart comparing average grades across skills or team members Learning Training progress bar chart showing learning completion by skill Switching between Manager and Employee grades When in the Skills Matrix view, two grade tabs appear at the top of the grid: Manager — Displays grades that managers have assessed for each team member Employee — Displays the self-assessed grades that team members have submitted Switching between these tabs updates every cell in the grid simultaneously. Use this to compare how a manager’s view of proficiency aligns with team members’ self-assessments. ​ Filtering Your Team’s S --- ## Analyze Training URL: https://help.skillsdb.com/manager-guide/analyze-training Quick Summary: The Training section gives managers three views for monitoring team training activity. All Activity shows a combined table of learning plan items and training approval requests. The Training Matrix shows a skill-by-person grid with training dates and statuses. Use both views to track progress, identify gaps, and manage training records directly. ​ Overview The Training section in the manager view provides two complementary tools for understanding and managing training across your team: All Activity — a flat table that combines all learning plan activity and training approval requests for your team members. Use this view to see what resources people are working through, monitor the status of training approvals, and identify who has completed or is still working on a specific training item. Training Matrix — a skill-by-person grid showing training dates and statuses at a glance. Use this view to see coverage across your team, identify expired or expiring training, filter by role or department, and manage individual training records directly from within the grid. Career Overview — a per-career dashboard for managers that surfaces training progress, expiration warnings, stat cards, progress breakdowns by section and label, a mini training matrix, and an Expert matrix preview. The Career Overview appears for any career that has Training Dates enabled in Career Settings. Overall Training Status — an all-careers dashboard that aggregates training progress across every career with Training Dates enabled. It surfaces stat tiles (Focus, Training Expirations, People Behind Target, People On Track), a Team Progress list, progress breakdowns, and links to the all-careers Training Matrix by Label and Expert Matrix. These views complement each other. Use All Activity for a unified feed, the Training Matrix for coverage and gap analysis across skills, the Career Overview for a high-level progress snapshot on a single career, and Overall Training Status for the cross-career picture. Administrators can view company-wide data. In All Activity and Overall Training Status, turn both scope chips off to show all data you can access. The Training Matrix has a separate scope selector. ​ Navigating to Training To access the Training section select Training from the left sidebar navigation under the Team section. The page opens in the All Activity view by default. To switch to the Training Matrix , select the All Activity breadcrumb at the top of the page and choose Training Matrix from the dropdown. To open the Career Overview for a specific career, navigate to Team > Skills , select the career you manage, and open its overview page. The Career Overview is the default landing view for a career when Training Dates are enabled in Career Settings. ​ Using the All Activity View The All Activity view combines two types of training records into a single table: Learning Plan — items from your team members’ personal learning plans, including resources assigned by you, an administrator, or added by the employee themselves Training Approval — training requests submitted against specific skills in your team members’ Careers Both types appear together, giving you a unified view of all active and historical training in one place. Scope chips Select Direct Reports , My Org , both, or neither. Selected chips stay highlighted; select a chip again to turn it off. With neither selected, the page shows all data your permissions allow. My Org already includes direct reports, so selecting both shows the same people as My Org without duplicates. There is no separate All chip. Scope What it shows Direct Reports Training activity for your immediate direct reports only My Org Training activity across your full reporting organization, including indirect reports Columns Column Description Name The team member’s name and email address Training The title of the learning resource or training item Labels Labels applied to the resource. Shown for Learning Plan items only Type Whether the row is a Learning Plan item or a Training Approval Status The current status of the activity (see status reference below) Assigned By For Learning Plan items: who assigned the resource. For Training Approvals: who submitted the request Started For Learning Plan items: the date the employee started the resource. For Training Approvals: the date the approval was requested Completed For Learning Plan items: the date the employee completed the resource. For Training Approvals: the date the approval was approved Additional columns — Employee ID, Employee Email, Manager Name, and Manager Email — are available but hidden by default. Use the Display button to show or hide them. Status reference Status Color Meaning Awaiting Approval Yellow A training approval has been submitted and is waiting for manager action Pending Yellow Activity is pending and has not yet been started or actioned In Progress Blue The employee is actively working through this resource Not Started Gray The resource has been assigned but the employee has not yet started Completed Green The resource has been completed by the employee Approved Green The training approval has been approved Rejected Red The training approval has been rejected Filtering All Activity Use the filter bar above the table to narrow results by one or more values: Name — Filter by employee name Training — Filter by training resource title Type — Filter by activity type: Learning Plan, Training Approval, or both Status — Filter by one or more status values Filters can be combined. To clear all active filters, select Reset in the filter bar. Exporting All Activity To export the All Activity table to Excel: Select Export in the top right of the page. SkillsDB downloads a file named All_Training_Activity_{date}.xlsx containing all rows currently visible in the table, respecting any active filters. ​ Using the Training Matrix The Training Matrix is a pivot-style grid that displays training dates and statuses for your --- ## Build Learning Plans URL: https://help.skillsdb.com/manager-guide/build-learning-plans Quick Summary: As a manager, you can view and contribute to your direct reports’ learning plans — adding resources, tracking progress, and updating completion status to support their development. ​ Overview SkillsDB gives managers visibility into and control over their direct reports’ learning plans. A learning plan is a personal collection of learning resources — from your organization’s training library or added manually — that tracks an individual’s development activity. As a manager, you can open any direct report’s learning plan, see what resources they are working on, add new resources on their behalf, track completion progress, and export plan data for reporting purposes. Every resource in a learning plan displays who added it and when, so both you and your team member have full visibility into the plan’s history. Managers can add two types of resources to a team member’s learning plan: Library resources — Training content from your organization’s centralized library, assigned directly to the individual from the library record Custom resources — Manually created entries with a title, category, description, URL, and estimated duration Note: Team members can also manage their own learning plans independently. This article covers the manager experience. See Building a Learning Plan for the team member perspective. ​ Prerequisites Before building learning plans for your team, you need: Permission level: Manager role with at least one direct report in SkillsDB Setup requirement: Your team members must have active SkillsDB accounts Standard users cannot view or edit other users’ learning plans. Only managers and administrators can access a team member’s learning plan. ​ Viewing a Team Member’s Learning Plan To access a team member’s learning plan: Select People from the Team section in the left sidebar Select your team member’s name from the direct reports list Select the Learning Plans tab on their profile page The learning plan opens in Board view by default, displaying resources organized into Kanban columns by status. To switch to a row-based layout, select Display in the top right and choose Table . Each resource card or row displays: Field Description Learning Plan The resource name and description Category The learning type (shown as a badge) Added by The name of the person who added the resource and the date it was added Rating Thumbs rating for library resources (not available for custom resources) Status Current progress status: To Do, In Progress, Completed, or Archived ​ Adding a Custom Resource to a Team Member’s Plan Custom resources are learning entries you create manually — such as a book recommendation, an internal workshop, an online course, or any other development activity that isn’t in the organization’s training library. Navigate to the team member’s Learning Plans tab (see steps above) Select Add resource in the top right corner of the screen In the Add new learning modal, complete the following fields: Field Required Description Title Yes Name of the learning resource Description No Additional context or notes about the resource Category Yes Learning type — select from the dropdown list URL No Link to the resource (must start with http:// , https:// , or www. ) Duration No Estimated time to complete, in hours Select Submit The resource appears in the team member’s learning plan under the To Do column. The Added by field shows your name and today’s date, giving the team member full context on who recommended the resource. Tip: Use the Description field to explain why you’re recommending this resource — for example, “This covers the SQL fundamentals identified in your last skills review.” A brief note helps your team member understand the context. ​ Editing and Removing Custom Resources You can edit or delete custom resources that you or another manager have added to a team member’s plan. Library resources cannot be edited, but can be unassigned from the team member’s profile. To edit a custom resource: Navigate to the team member’s Learning Plans tab Locate the resource card and open its action menu Select Edit Update the fields in the Update Custom Learning modal Select Save To delete a custom resource: Locate the resource card and open its action menu Select Delete Confirm the deletion Warning: Deleting a custom resource permanently removes it from the team member’s learning plan, including any progress recorded against it. This action cannot be undone. ​ Tracking and Updating Progress You can update the progress on any learning plan item for a team member — recording hours spent and overall completion percentage. Navigate to the team member’s Learning Plans tab Locate the resource card and select Update In the Update duration and progress modal, enter: Duration — Total estimated hours for the resource (up to 2 decimal places) Percent Complete — Current completion percentage from 0 to 100 (up to 2 decimal places) Select Save Marking a resource as complete To mark a resource as complete, open the action menu on the resource card and select Complete . If the resource has a duration recorded and the percent complete is below 100, a confirmation modal appears asking how to record the final hours: Complete with [completed hours] hours — Records the hours already logged Complete with [full duration] hours — Records the full estimated duration Select the option that best reflects the actual time spent, then select Complete . The resource moves to the Completed column and cannot be moved back to In Progress directly. If a completed resource needs to be restarted, archive it first and then move it to In Progress . ​ Moving Resources Between Statuses Learning plan resources progress through four statuses. You can update a team member’s resource status by dragging cards between columns in the Board view, or by using the action menu in either view. Status Meaning To Do Resource is queued but not yet started In Progress Team member is actively working on this resource Comple --- ## Certification Tracking URL: https://help.skillsdb.com/manager-guide/certification-tracking Quick Summary: The Team Certifications page gives managers a consolidated view of every certification assigned to their team members. From here you can monitor submission status, track expirations, review pending approvals, and export data for reporting. ​ Overview The Team Certifications page displays all certifications assigned to people in your reporting structure. Each row represents one person-certification combination, showing the team member’s name alongside the certification details, current status, expiration date, and any attached files. This page is your primary tool for monitoring certification compliance across your team. You can quickly identify which team members have certifications awaiting your approval, which certifications are expiring soon, and which team members have not yet submitted their certification details. The page is accessible to managers and administrators. Managers see certifications for their direct reports and organizational hierarchy. Administrators can also view all certifications across the entire company. Note: This page shows certifications assigned to your team members. For managing your own personal certifications, see Managing Certifications . ​ Navigating to Team Certifications To open the team certifications view select Certifications from the My Team section of the left sidebar. The page opens in the default scope for your role: Direct Reports for managers and company-wide data for administrators with that access. ​ Switching Between Views The ACE filter row at the top of the page narrows certifications by scope. The Direct Reports and My Org filters can be selected together, alongside an Approvals button that opens your Inbox: View What it shows Direct Reports Certifications for your immediate direct reports only My Org Certifications across your full reporting organization, including indirect reports Approvals Navigates to your Inbox where you can review and action pending certification approval requests Select Direct Reports , My Org , both, or neither. Selected filters stay highlighted; select a filter again to turn it off. With neither selected, the page shows the broadest data your permissions allow. My Org already includes direct reports, so selecting both shows the same people as My Org without duplicates. Administrators with company-wide access see the All scope by default when no scope filter is selected. Note: Clearing scope filters preserves your access restrictions. Company-wide certification visibility still requires the appropriate administrator permissions. ​ Understanding the Certifications Table The table displays one row per person-certification combination. The following columns are visible by default: Column Description Name The team member’s full name. Select a row to open the certification detail page for that person. Certification The certification name. Status The current status of the certification (see Understanding certification statuses below). Expires The expiration date with a visual indicator: Expired (red), Expiring Soon (amber), or valid date. Type The certification type or category, as configured by your organization. Files The number of supporting documents attached to the certification. Additional columns (hidden by default, enable via the Display button): Column Description Labels Any labels applied to the certification. Employee ID The team member’s employee ID. Employee Email The team member’s email address. Issued Date The date the certification was first granted. ID Number The credential ID or certification number. Careers The team member’s assigned career. Manager The team member’s direct manager name. Department The team member’s department. To show or hide columns, select the Display button in the top right of the page. ​ Understanding Certification Statuses Each certification has a status that reflects where it is in the submission and review process. Status Displayed as Meaning Assigned Submit Details The certification has been assigned to the team member. They need to submit their details. Awaiting Approval Awaiting Approval The team member has submitted details and is waiting for manager or administrator review. Approved Approved The certification details have been approved. Denied Denied The submission was rejected. The team member can resubmit updated details. Expired Expired The certification has passed its expiration date. Modified Modified The certification details have been updated after a previous approval. ​ Reviewing and Approving Certifications When a team member submits their certification details, the status changes to Awaiting Approval . You can review and approve or deny the submission. To review a pending certification: Select Certifications from the Team section of the left sidebar. Use the Status filter to show only Awaiting Approval certifications, or select Approvals to go to your Inbox. Select the row of the certification you want to review. This opens the certification detail page. Review the submitted details — issued date, expiration date, credential ID, and any attached documents. Select Approve to accept the submission, or Reject to return it to the team member for corrections. When you approve a certification, its status changes to Approved and the team member receives a notification. When you reject it, the status changes to Denied and the team member can resubmit with updated information. Tip: Select Approvals in the top filter bar to go directly to your Inbox, where all pending certification approvals are consolidated alongside other approval requests. ​ Filtering Your Team’s Certifications Use filters to narrow the table to a specific subset of certifications. Select Filter in the toolbar to open the filter builder. Available filters include: Filter Description Name Filter by team member name Certification Filter by certification name Status Filter by one or more certification statuses Expires Filter by expiration timing: soon (next month) or a custom date range Iss --- ## Customizing Benchmarks URL: https://help.skillsdb.com/manager-guide/customizing-benchmarks Quick Summary: Benchmarks are target proficiency levels you assign to team members for specific skills during a manager assessment. Set them one at a time or in bulk from the batch grading view to measure skill gaps and track development progress across your team. ​ Overview A benchmark is the expected or target proficiency level for a team member on a given skill. When you assign a benchmark during a manager assessment, SkillsDB compares it to the person’s actual grade and displays the gap throughout the platform — in the batch grading table, the Skills Matrix, and the Career Overview scorecard. Benchmarks give managers a structured way to communicate performance expectations. Rather than tracking grades in isolation, you can define what “good” looks like for each person and skill combination, then see at a glance who is meeting the target and who needs support. Benchmarks are entirely separate from grades. A grade reflects what a person currently knows; a benchmark reflects what they are expected to know. Both can exist independently — a person can have a benchmark without yet having a grade, or a grade without a benchmark. Managers and administrators can set and update benchmarks. Standard employees cannot set or modify benchmarks, but they can see their own benchmark values in their skills profile. Note: Benchmarks use the same proficiency scale as regular grades. The exact scale labels — for example, “Developing,” “Proficient,” “Expert” — are configured by your organization’s administrator. The available options shown in the benchmark selector will match your account’s grading scale. ​ Prerequisites Before you set benchmarks, you need: Permission level : Manager or Administrator role in SkillsDB Active assessment : At least one team assessment that has not yet been submitted. Benchmarks cannot be added or changed on submitted assessments. Access : Navigate to Team > Assessments and open an active assessment ​ Opening the Batch Grading View Benchmarks are set from within the manager assessment workflow. To reach the batch grading view: Select Assessments from the Team section of the left sidebar. The My Team Assessments page opens, listing all active and available assessments for your team. Locate the assessment you want to work on and select Begin or Continue . The batch grading view opens. The batch grading view displays one skill at a time. For each skill, a table lists your team members in rows. The columns include the person’s name, prior grade, new grade, a Focus toggle, and a Benchmark column. Note: The Benchmark column is hidden on smaller screens. If you do not see the Benchmark column, widen your browser window or use a larger display. ​ Setting a Benchmark for a Single Team Member Use this approach when you want to assign a target proficiency level to one person for the currently visible skill. In the batch grading table, locate the team member’s row. Select the cell in the Benchmark column for that person. Alternatively, use the keyboard arrow keys to highlight the person’s row, then press B . A dropdown opens showing the available proficiency levels from your organization’s grading scale, sorted highest to lowest. Select the target grade from the list. Each option shows the grade number alongside its description. The benchmark saves immediately and the Benchmark column updates to reflect the new value. Keyboard shortcuts within the benchmark selector: Key Action Number keys Select the grade that matches the number pressed Up / Down Navigate up or down through the grade options Enter Save the selected grade and close Esc Cancel without saving Tip: Use number keys to set benchmarks quickly. If your grading scale runs from 1 to 5, press 3 to instantly select grade 3 as the benchmark. Combined with arrow key row navigation, you can set benchmarks for your entire team without touching the mouse. ​ Setting Benchmarks for Multiple Team Members at Once When you want to apply the same benchmark to several people simultaneously, use multi-select mode. This is useful when a cohort of team members shares the same role or development expectations. In the batch grading table, select the first person’s row by clicking it. Hold Shift and click another row to select a contiguous range, or hold Ctrl (Windows) / Cmd (Mac) and click individual rows to select non-contiguous people. Selected rows are highlighted in blue. Press B on the keyboard to open the benchmark selector. The dialog title reads Update Benchmark for [N] People , confirming how many people are in your selection. Select the target grade. Select Save . When you save, SkillsDB applies the same benchmark to every selected person for the current skill. People whose assessments have already been submitted are automatically skipped. Important: Bulk benchmarks apply only to the skill currently displayed in the batch grading view. To set benchmarks for a different skill, navigate to that skill using the skill list in the left panel and repeat the process. ​ Clearing a benchmark To remove a benchmark from a team member, open the benchmark selector and select the lowest grade option (grade 0 if available on your grading scale), or simply re-open the selector and choose a new value to replace the existing one. If your grading scale does not include a 0 value, contact your SkillsDB administrator. Benchmarks can always be updated to a different grade level within an active assessment. ​ How Benchmarks Appear in SkillsDB Once you set benchmarks, they influence how skill data is displayed across the platform. ​ In the batch grading table The Benchmark column shows a grade bar visualization for each team member. This gives you a visual reference for the target level as you grade. ​ In the Skills Matrix When you open the Skills Matrix from the Career Overview, each grade cell displays an indicator comparing the person’s actual grade to the benchmark: Indicator Color Meaning Up arrow Blue Grade exceeds the benchmark Star Green Grade exactly m --- ## Getting Started for Managers URL: https://help.skillsdb.com/manager-guide/getting-started ​ Welcome, Managers! 👋 SkillsDB gives you the tools to manage your team’s skills, track training, and drive development — all in one place. Whether you’re reviewing assessments, analyzing skill gaps, or building learning plans, this guide will help you get started quickly. Book a Call | Contact Support ​ Getting Started 1 View Your Team Head to the Team section to see an overview of your direct reports, their roles, and current skill levels. View Your Team → 2 Run Assessments Initiate or review manager assessments for your team members to evaluate their current skill levels. Manager Assessments → 3 Analyze Skills & Training Use the Analyze Skills and Analyze Training dashboards to identify gaps, trends, and opportunities across your team. Analyze Skills → | Analyze Training → 4 Build Learning Plans Create and assign learning plans to help your team members close skill gaps and grow in their roles. Build Learning Plans → 5 Track Certifications Monitor your team’s certifications and stay ahead of upcoming expirations. Certification Tracking → ​ Key Manager Features Viewing Your Team See your full team roster with roles, skills, and assessment status at a glance. Manager Assessments Run and review skill assessments for your direct reports. Analyze Skills Identify skill gaps and strengths across your team. Analyze Training Track training completion and measure its impact. ​ More Tools Certification Tracking Stay on top of team certifications and expiration dates. Build Learning Plans Create targeted learning paths for your team members. Customizing Benchmarks Set skill grade expectations tailored to your team. Promotion Workflows Review and manage team promotion readiness. Team Learning Plans Monitor learning plan progress across your team. Looking for other guides? Check out the User Guide . ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Manager Assessments URL: https://help.skillsdb.com/manager-guide/manager-assessments Quick Summary: Manager assessments let you grade your direct reports’ skill proficiency across their assigned roles. You can grade team members one at a time or work through your whole team skill by skill using batch grading. When both you and your team members complete your assessments, results appear side-by-side on each person’s scorecard. ​ Overview A manager assessment is a formal evaluation cycle in which you grade the skill proficiency of your direct reports. Manager assessments run in parallel with employee self-assessments — while your team members grade their own skills independently, you assess each of them using your organization’s grading scale (typically 1–5). When both are complete, the scorecard shows your grades and the employee’s self-assessed grades side-by-side for comparison. Manager assessments exist to provide an independent perspective alongside each employee’s self-reported proficiency. Together, manager and self-assessments give your organization a more complete picture of skills across the team, which feeds into skills gap analysis, development planning, and workforce reporting. Assessments are created and assigned by administrators. You receive manager assessments for the direct reports assigned to you in SkillsDB. You do not create assessments yourself — if you believe you should have an active assessment but cannot see one, contact your administrator. Note: Manager and self-assessments are completed independently. By default, you cannot see your team members’ self-assessed grades while you are grading, and they cannot see yours. Both sets of grades become visible on the scorecard once the assessment is complete. ​ Navigating to Your Team’s Assessments To view your active assessments select Assessments from the My Team section of the left sidebar. The My Team Assessments page shows all assessments currently assigned to you, including completed and ended ones. ACE quick filters — Not Started , In Progress , Completed , and Ended — narrow the list. You can select several statuses at once; results match any selected status. Select an active filter again to clear it. With no status filters selected, all available statuses appear, so there is no separate All filter. Draft assessments are not shown. Each row in the table displays: Column Description Assessment The title of the assessment Status The current status indicator (Not Started, In Progress, Completed, Ended) Progress Your grading completion percentage, shown as a number and a visual progress bar Deadline The manager deadline date for submitting your grades Action Start , Continue , or Results depending on your progress Select an assessment title or its action button to open it. ​ Opening an Assessment Selecting an assessment opens its details page. This page is your home base for the full assessment — it shows overall progress, individual team member status, and your two grading options. Assessment metadata A card at the top of the page shows key information about the assessment: Field Description Status The current status of the assessment Manager deadline The date by which you must submit your grades Employee deadline The date by which your direct reports must complete their self-assessments Employees The number of direct reports assigned to this assessment Last nudge sent The date you last sent a reminder to your team to complete their self-assessments Batch grading card A prominent card shows your overall grading progress across the entire team, with a progress bar and a Start or Continue button. This is the entry point to batch grading. See Batch grading below for details. Direct reports table The table lists each of your direct reports with their current assessment status: Column Description Employee Team member’s name Employee Assessment The employee’s self-assessment progress Manager Assessment Your grading progress for this person Action buttons available for each employee: Button When it appears Action Start Manager assessment not yet begun Opens the individual grading flow Continue Grading in progress Returns to where you left off Submit All skills graded but not yet submitted Submits this person’s assessment Scorecard Assessment submitted for this person Opens the results scorecard View Profile Always Opens the employee’s Skills Profile You can search for a specific team member using the search input above the direct reports table. The table filters by first or last name as you type. ​ Grading an Individual Team Member Individual grading lets you work through one team member’s skills at a time. This is best when you want to give each person careful attention, review skill-by-skill context, or add comments as you grade. Starting individual grading In the direct reports table, select Start or Continue next to a team member’s name. When opening an assessment for the first time, an intro modal appears before you begin grading. Step 1 — Keyboard shortcuts: The first screen shows all available keyboard shortcuts. Key Action 1 – 5 Assign a grade to the current skill N Toggle Not Applicable for the current skill → Move to the next skill ← Move to the previous skill Enter Move to the next skill (or submit on the final skill) ? Open the keyboard shortcuts reference Esc Exit the grading interface Select Continue to proceed. Step 2 — Assessment overview: A summary screen shows key information before you begin. Card Description Deadline The manager deadline and how many days remain Total Skills The number of skills you need to grade for this person Est. Time Estimated time to complete (approximately 2 minutes per skill) Progress Your current completion percentage, if you have already started Select Start Assessment to begin. If you are returning to a partially completed assessment, the button reads Continue Assessment . Understanding the grading layout The grading interface is divided into three panels: Panel Purpose Left sidebar Skills list grouped by job role, with completion checkmarks Center The current --- ## Promotion Workflows URL: https://help.skillsdb.com/manager-guide/promotion-workflows Quick Summary: Promotion workflows let you assign structured career advancement checklists to your direct reports, track their progress in real time, and approve or reject completion requests when they’re done. ​ Overview A promotion workflow is a structured checklist of requirements an employee must complete to demonstrate readiness for career advancement. Your organization’s administrators create and publish these workflow templates. As a manager, you assign them to your direct reports, monitor their progress, and approve completions. Each promotion workflow is made up of one or more content blocks — which may include written requirements, reference links, attachments, and individual tasks the employee must check off. Employees work through the workflow at their own pace. When they’ve finished all tasks, they submit the workflow for your review. You then approve or reject the submission. Promotion workflows give your team a transparent, auditable record of what advancement criteria exist and whether an employee has met them. This helps standardize how promotion decisions are made across your organization and gives employees a clear picture of what is expected of them. Managers can assign workflows to team members, monitor their progress, and approve or reject completion requests. Administrators configure the workflow templates and can scope them to specific departments, teams, or sites. Note: Only administrators can create, edit, and publish promotion workflow templates. If no templates are available to assign, contact your SkillsDB administrator. ​ Prerequisites Before working with promotion workflows, make sure: Permission level : Manager role or higher in SkillsDB Template availability : At least one promotion workflow template has been published by an administrator Team access : You have direct reports assigned under your account in SkillsDB ​ Understanding Promotion Workflow Statuses When a promotion workflow is assigned to a team member, it moves through four statuses: Status What it means To Do Workflow has been assigned; the employee has not yet started In Progress The employee has begun completing tasks Approval Requested The employee has completed all tasks and submitted for your review Complete You have approved the submission; the workflow is closed Note: Some promotion workflows are configured to require both manager approval and administrator approval before reaching Complete status. In those cases, your approval advances the workflow to a pending admin review state. ​ Assigning a promotion workflow to a team member Assign a promotion workflow when a team member is ready to begin working toward a specific promotion or advancement milestone. Select People from the Team section in the left sidebar. Select the team member’s name to open their profile. Select the Qualifications tab. Locate the workflow you want to assign in the list. Select Assign next to that workflow. When you assign a workflow, the system assigns the current published version of that template to the employee. The status is set to To Do and the employee can immediately begin working through the requirements. You can assign multiple promotion workflows to the same employee simultaneously. This is useful when a team member is pursuing advancement across more than one competency area. ​ Removing a promotion workflow assignment To remove a promotion workflow from a team member: Navigate to the team member’s profile and select the Qualifications tab. Locate the assigned workflow. Select Unassign next to the workflow. Warning: Unassigning a promotion workflow permanently removes the employee’s progress record for that workflow, including all completed tasks. This action cannot be undone. ​ Reviewing and approving a completion request When an employee completes all tasks in their promotion workflow, they submit it for your review. The workflow status changes to Approval Requested and a notification appears in your Inbox . To review and act on a completion request: Select Inbox from the left sidebar to view pending approval requests. Select the relevant notification to open the workflow detail view. Review the completed tasks and any attached documentation the employee has provided. Select Approve to accept the completion, or Reject to return it to the employee. When you approve: The workflow status changes to Complete . A completion record is saved with the approval date and approving manager’s name. The employee receives a notification confirming the approval. When you reject: The workflow status returns to In Progress . The employee receives a notification that the request was rejected. The employee’s previously completed tasks remain checked and they can continue working or make corrections before resubmitting. Note: You can also navigate directly to the employee’s profile and select the Qualifications tab to access a pending approval request, without going through the Inbox. ​ Advanced options Workflow versions Promotion workflow templates are versioned by administrators. When a template is updated, existing employee assignments are not automatically changed — employees continue working on the version they were originally assigned. New assignments always receive the latest published version. If a team member is working on a significantly outdated version of a workflow, you can unassign and reassign the workflow to update them to the current version. Doing so will clear their existing progress data. Org unit scoping Administrators can scope promotion workflows to specific departments, teams, sites, or other organizational units. If an expected workflow template does not appear when you go to assign it, confirm with your administrator that the workflow has been scoped to your team or department. Recurring workflows Some promotion workflows are configured to repeat on a schedule (for example, annually or after a set number of days from completion). When a recurring workflow is completed and approved, a new assign --- ## Team Learning Plans URL: https://help.skillsdb.com/manager-guide/team-learning-plans Quick Summary: The Team Learning Plans page gives managers a consolidated table of all learning plan items across their team, with tabs for direct reports, full org, and company-wide views. ​ Overview The Team Learning Plans page provides a single table showing every learning plan item assigned to people in your reporting structure. Each row represents one person-resource combination, displaying the team member’s name alongside the learning resource, its current status, who assigned it, and when it was started or completed. This page complements the individual learning plan view available on each team member’s profile. While the profile view lets you manage a single person’s plan, the Team Learning Plans page gives you a cross-team view to quickly identify who is progressing, who has not started, and which resources are most commonly assigned. Managers see learning plans for their direct reports and organizational hierarchy. Administrators can view all learning plans across the entire company. ​ Navigating to Team Learning Plans To open the team learning plans view, navigate directly to the /myTeamLearningPlans URL. Note: The Team Learning Plans page is not currently listed in the sidebar navigation. Access it directly via the URL or through internal links. ​ Switching Between Views Three tabs at the top of the page control the scope of learning plans displayed: Tab What it shows Direct Reports Learning plan items for your immediate direct reports only My Org Learning plan items across your full reporting organization, including indirect reports All All learning plan items across the entire company (available to administrators only) Select a tab to switch views. The active tab is underlined. ​ Understanding the Learning Plans Table The table displays one row per person-resource combination. Name , Learning , Status , Assigned By , Date Started , Date Completed , and Labels are shown by default. The remaining columns are available but hidden — enable them from Display . Column Description Employee ID The team member’s employee identifier Name The team member’s name Employee Email The team member’s email address Manager Name The name of the team member’s manager Manager Email The email address of the team member’s manager Learning The title of the learning resource Status The current status: NotStarted, InProgress, Completed, or Archived Total Hours The total hours estimated for the resource Hours Complete The hours the team member has logged so far Percent Complete The completion percentage the team member has recorded Assigned By The name of the person who assigned the resource (blank if self-assigned) Date Started The date the team member started working on the resource Date Completed The date the team member completed the resource Labels Any labels applied to the learning resource Each column supports sorting and filtering via the column header controls. ​ Exporting Learning Plan Data You can export the current table view to Excel for reporting or offline analysis. To export: Select Export in the top right of the page. SkillsDB downloads an Excel file containing all rows currently visible in the table, respecting the selected tab and any active column filters. ​ Common Questions What is the difference between Team Learning Plans and a team member's individual Learning Plans tab? The individual Learning Plans tab on a team member’s profile lets you view, add, edit, and manage learning resources for that specific person. The Team Learning Plans page shows all learning plan items across your team in a single consolidated table, making it easier to compare progress and identify patterns across multiple people. Can I add or edit learning resources from this page? No. The Team Learning Plans page is a read-only monitoring view. To add or manage resources for a specific team member, navigate to their profile and select the Learning Plans tab. See Build Learning Plans for details. Why don't I see the All tab? The All tab is restricted to administrators. It provides company-wide visibility across all learning plans, not limited to your reporting structure. If you need access, contact your SkillsDB administrator. ​ Related Articles Build Learning Plans Add and manage learning resources for individual team members Building a Learning Plan How team members manage their own learning plans Analyze Training Monitor training activity and completion across your team Viewing Your Team Navigate your team roster and access individual profiles ​ Need Help? If you run into any issues or have questions, reach out to your organization’s SkillsDB administrator or contact SkillsDB Support . --- ## Viewing Your Team URL: https://help.skillsdb.com/manager-guide/viewing-your-team Quick Summary: The People page gives managers a complete, filterable roster of their team — including direct reports and broader org hierarchy — with quick access to each person’s profile, training record, certifications, and more. ​ Overview The People page is your central team directory in SkillsDB. It displays everyone in your reporting structure in a single, scrollable table so you can quickly find team members, review their organizational details, and navigate to their individual profiles. The page lets you narrow the roster to your direct reports or full organizational span of control, or leave the scope unfiltered to see all people you can access. This makes it useful whether you manage a small team or oversee a larger multi-level organization. The People page is only visible to users with a manager role or above. From here you can navigate to dedicated Team pages for skills analysis, training records, assessments, and certification tracking. ​ Navigating to Your Team Select Team from the left sidebar to expand the Team section, then select People . The page opens displaying your team roster. Note: The Team section only appears in the sidebar if you have a manager role. If you do not see it, contact your SkillsDB administrator to confirm your role assignment. ​ Switching Between Views Scope lenses at the top of the page control which people are included in the table: View What it shows Direct Reports Only the people who report directly to you My Org Your full span of control — everyone in your organizational hierarchy, including people who report to your direct reports Recently added Recently created people you can access; available to Global Admin and Full Access users Select any combination of the available chips. Selected chips stay highlighted; select a chip again to turn it off. With no chips selected, the page shows all data your permissions allow. My Org already includes direct reports, so selecting those two shows the same people as My Org without duplicates. There is no separate All chip. Recently added stays visible when you select another scope, including when there are no recent matches. If you select My Org and Recently added , then the table includes people in either group, without duplicates. Existing advanced filters narrow the combined result. Changing a chip preserves your other selections, and reloading the page preserves the selected chips. Selecting Recently added displays an Added after [date] filter. Edit its date or operator to change the date condition for that group; everyone in a selected reporting scope remains included. Removing the Added filter or turning off Recently added removes that date condition and keeps the reporting scopes selected. Without Recently added , an Added filter applies to the whole selected scope. Tip: Use Direct Reports for day-to-day team management. Use My Org when you need to see the full depth of your organization — for example, when reviewing skills coverage across multiple reporting levels. ​ Understanding the Team Table The team table displays one row per person. The following columns are available: Column Description Name Person’s name and email address. Select to open their full profile. User ID The employee ID assigned to this person. Careers The job role(s) assigned to this person. Select the cell to assign or update roles. Manager The person’s direct manager. Select to open the manager’s profile. Manager ID The manager’s employee ID. Hidden by default; enable via the column chooser. Status Active (green) or Inactive (red) — indicates whether the person’s account is active. Resume A link to any resume documents on file. Select to view or download. Certifications A link to the person’s certification documents. Select to view details. Training Record A summary of the person’s learning plans. Select to open a training details view. Organization The top-level organization entity this person belongs to. Business Unit The person’s assigned business unit. Division The person’s assigned division. Country The person’s country. Region The person’s business region. City The person’s city. Site The person’s assigned site or facility. Department The person’s department. Team The person’s team within their department. Shift The person’s assigned shift. The Name , User ID , Careers , and Manager columns are pinned to the left and remain visible as you scroll horizontally through the organizational columns. ​ Filtering Your Team Use filters to narrow the table to a specific subset of your team. ​ Using scope lenses Use the scope chips to choose which groups of people to include. Turn every selected chip off to restore the unfiltered scope. Other active filters still apply. ​ Using advanced filters For more granular filtering, open the filter builder panel: Select the filter icon in the search/filter bar. The filter builder opens with the following available filters: Filter Description Name Filter by one or more specific people Manager Filter by manager name Career Filter by job role or career path Status Filter by Active or Inactive Organization Filter by top-level org entity Business Unit Filter by business unit Division Filter by division Country Filter by country Region Filter by business region City Filter by city Site Filter by site or facility Department Filter by department Team Filter by team Shift Filter by shift Select a filter, then choose one or more values from the dropdown. Add additional filters as needed. The table updates in real time as filters are applied. To clear all filters, select Reset Filters . When active filters are applied, a badge indicator appears in the filter bar showing that filters are in use. ​ Customizing Columns You can show or hide columns to tailor the table to your needs. Select Display in the top right of the page. The column chooser panel lists all available columns. Toggle any column on or off. Close the panel. SkillsDB saves your column preferences for your current session. Note: Column pref --- ## Skills URL: https://help.skillsdb.com/skills Quick Summary: The Skills scope of Search lets you search and browse every skill in your organization’s catalog. Use it to understand how a skill is distributed across the org, find learning resources, see who has the skill and at what proficiency level, and benchmark your own standing against peers. ​ Overview The Skills explore feature gives every SkillsDB user a view into the organization’s full skill catalog — not just the skills assigned to their own role. You can search for any skill by name, filter results by career, grade level, or flag type, and click through to a detailed profile for each skill. Skill detail pages show aggregate data drawn from across the organization: how many people are assigned to a skill, how proficiency grades are distributed by department and job role, what learning resources exist for the skill, and which colleagues hold it. This gives you a broader frame of reference when thinking about your own development — you can see where a skill sits in the organization, how it is graded on average, and what training is available to help you improve. The Skills explore feature is available to all SkillsDB users. No special permissions are required to search for skills or view skill detail pages. ​ Finding Skills Skills are discovered through the Search page — a unified search tool that covers people, training, skills, careers, and certifications. To navigate to skill search: Select Search from the left sidebar. In the filter bar beneath the search input, select Skills to narrow results to skills only. To search for a skill: Type the skill name (or a keyword) into the search input. As you type, a suggestions dropdown appears grouped into categories such as Skill and Learning , showing matching skills and related training resources. Select a suggestion to add it as a structured filter, or press Enter to run a broad text search. Search results appear in a table below the input. Each row represents a skill that matched your search term or applied filters. An Export button appears in the top-right corner when results are available, allowing you to download results as an Excel file. Tip: You do not need to know the exact skill name. Searching for a broad keyword — such as “python” or “leadership” — returns all skills containing that term in their name or description. ​ Filtering Skill Results After running a search, you can refine results using filters and sub-filters. Adding filters: Type a keyword into the search input and select a suggestion to add it as a filter tag. Each active filter appears as a tag below the search bar. Select the x on any tag to remove it, or select Clear to remove all filters at once. Sub-filters: Some filter tags display a sub-filter icon. Select it to access additional refinement options such as Document Search . Filter matching mode: When multiple filters are active, you can choose how they interact: Match all — A skill must satisfy every filter you have set (more restrictive) Match any — A skill needs to satisfy at least one filter (broader results) ​ Understanding Search Results When the Skills scope is selected, the results table shows the following for each skill: Column What it shows Name The skill name, displayed as a link to the skill detail page Assigned The total number of people in the organization who have this skill assigned to their career path Criteria Tags showing which filters or search terms this skill matched Match A percentage score (0–100%) indicating how closely the skill matched your search criteria Skills are ranked by match score, with the most relevant results at the top. ​ Exploring a Skill Selecting any skill name in the results table opens the skill detail page. This page gives you a comprehensive profile of the skill across five tabs: Overview , Proficiency , Resource , Analytics , and Activity (the Activity tab is visible to administrators only). Use the dropdown in the breadcrumb bar to switch between tabs. A right sidebar displays Skill Details — including the average employee grade, manager grade, benchmarks, and training cost — alongside a Related section showing which careers and groups include this skill. Summary statistics At the top of every skill detail page, eight summary statistics give you an at-a-glance view of the skill’s footprint in the organization: Stat What it means Resources Number of learning resources available for this skill Skill Gaps Number of people assigned to this skill who have a grade below their benchmark Assigned Total number of people who have this skill assigned to their career path On Target Number of people who meet or exceed the benchmark grade for this skill Experts Number of people flagged as Expert for this skill Mentors Number of people flagged as Mentor for this skill Focused Number of people who have applied the Focus flag to this skill Interested Number of people who have applied the Interest flag to this skill Overview tab The Overview tab is the default view and provides a summary of the skill’s profile across the organization. The tab includes: A grade comparison chart showing the average employee grade, average manager grade, and benchmark grade side by side A preview of the top five people with this skill, showing their self-assessed and manager-assessed grades A snapshot of Analytics charts (by Department and by Job Role) View All — select to jump to the full Proficiency tab Full Report — select to jump to the Analytics tab Proficiency tab The Proficiency tab shows a complete table of every person who has this skill assigned, along with their grades. Column What it shows Name The person’s name and avatar Employee grade The person’s self-assessed proficiency grade, shown as a visual grade bar Manager grade The grade their manager has assessed for this skill Benchmark The expected proficiency level for this skill in their role Flags Any skill flags applied — Mentor, Focus, Interest, etc. Use this tab to understand how colleagues at different grades approach this s --- ## Training URL: https://help.skillsdb.com/training Quick Summary: The Training search lets you discover all training resources available in your organization’s library. Search by keyword, filter by provider, format, level, and more — then add resources to your learning plan or assign them to your team. ​ Overview The Training scope of Search is your gateway to discovering all training resources available in your organization’s catalog. Whether you are looking for a specific course, exploring options to build a particular skill, or identifying development opportunities for your team, the Training search surfaces your entire training library in one searchable, filterable view. Training resources in SkillsDB are created and managed by your organization’s administrators. Each resource can include a title, description, provider, format, duration, cost, and target audience. Resources may also have associated skills and custom labels to help you understand what they are designed to develop. Using the Training search, you can discover resources that match your goals, review key details at a glance, and take immediate action — adding resources to your own learning plan or assigning them to members of your team. Who this is for: Standard users can search the full training catalog, view resource details, and add training to their personal learning plan. Managers can do everything above, plus assign training resources directly to team members. Administrators can do everything above, plus open the training edit form directly from search results. ​ Navigating to Training Search Select Search from the left sidebar. In the scope selector at the top of the search bar, select Training . The search bar updates to show “Find Training…” as a placeholder, and the results area refreshes to show training-specific filters and results. Note: If you navigate to Search without selecting a specific scope, the page defaults to All , which returns mixed results across all resource types. Select Training from the scope selector to see only training resources. ​ Searching for training The Training search supports free-text search across your organization’s full training catalog. In the search bar, type a keyword — for example, the name of a course, a skill topic, or a provider name. Results appear automatically as you type. Each row in the results table represents one training resource. What each result row shows: Field Description Training title The name of the training resource Provider The organization or platform delivering the training Duration Estimated time to complete, in hours Cost Cost of the training, if applicable External link icon Appears next to the title if the training links to an external URL Criteria The search terms and filter values that matched this result (see below) Understanding the Criteria column The Criteria column shows every filter and search term that was active when results were returned. Criteria that matched the result are displayed in full color. Criteria that did not match are shown in faded text. This lets you see at a glance why a particular result was returned and which of your filters it satisfies. ​ Filtering Results Use filters to narrow results by specific attributes. Filters are accessible via the Filter button to the right of the search bar. Select Filter to open the filter panel. Apply one or more of the following filters: Filter Description Training Provider Filter by the organization or platform delivering the training Training Format Filter by delivery method (e.g., Online, In-Person, Hybrid) Training Audience Filter by the intended audience for the training Course Level Filter by difficulty level (e.g., Beginner, Intermediate, Advanced) Cost Enable to filter by a cost range Duration Enable to filter by a duration range (in hours) After applying filters, select Match all or Match any to control how multiple filters interact: Match all — Returns results that satisfy every active filter (AND logic) Match any — Returns results that satisfy at least one active filter (OR logic) Active filters appear as tags below the search bar. Select the x on any tag to remove that filter individually, or select Clear to remove all filters and search terms at once. Tip: Use Match any when you want a broad set of results across multiple providers or formats. Use Match all when you need results that specifically satisfy several criteria at once — for example, online courses at beginner level from a particular provider. ​ Adding Training to Your Learning Plan Any training resource you find in the search results can be added directly to your personal learning plan. Locate the training resource you want to add. In the Actions column, select Add to My Learning . The training is added to your learning plan immediately. The button updates to Assigned to You to confirm the addition. Note: Once a training is added to your learning plan, the Add to My Learning button is replaced with Assigned to You and becomes inactive. The training will appear in your learning plan under the To Do status. See Building a Learning Plan for instructions on managing your plan. ​ Viewing Training Details Selecting a training resource opens the full details page for that resource, where you can review its complete description, associated skills, and other attributes. Select anywhere on a training row (except the action buttons) to open the training details page. The details page displays the full training record, including all fields configured by your organization’s administrators. Use your browser’s back button to return to your search results. ​ Assigning Training to Team Members (managers) Managers can assign any training resource to one or more members of their team directly from search results. Locate the training resource you want to assign. In the Actions column, select Assign . In the Assign dialog that opens, select the team members you want to assign the training to. Confirm the assignment. The training is added to the selected team members’ learning plans. Eac --- ## AI Transformation URL: https://help.skillsdb.com/tutorials/ai-transformation Quick Summary: This tutorial walks through the complete SkillsDB workflow for organizations navigating an AI transformation — from defining an AI competency framework and baselining skill levels, to building learning pathways, running manager assessments, tracking certifications, and monitoring progress at scale. ​ Overview AI transformation is one of the most complex workforce challenges organizations face today. Employees need new skills quickly, at every level of the organization, while leaders need visibility into where capability gaps exist and whether upskilling efforts are working. SkillsDB gives HR teams, learning and development leaders, and managers a unified platform to manage every stage of an AI transformation initiative. Rather than relying on spreadsheets or disconnected tools, you can define your AI competency expectations, measure where your workforce stands today, deploy targeted learning resources, and track progress — all in one system. This tutorial covers the full workflow from initial setup through ongoing monitoring. It is organized into phases that map to how a transformation typically unfolds. Each phase identifies who is responsible and what actions they take. Who this tutorial is for: Administrators — Build the skills framework, configure careers, and manage the platform Managers — Assess team members, set benchmarks, assign learning, and track progress Employees — Complete self-assessments, pursue learning resources, and track their own development ​ Phase 1: Build Your AI Competency Framework Who does this: Administrators Before you can assess or develop AI skills, you need to define what AI competency means for your organization. This means structuring an AI career path, creating the individual skills that make it up, and defining what proficiency looks like at each level. ​ Create an AI career path A career path in SkillsDB is the top-level grouping that organizes related skills into a coherent development track. For AI transformation, you will typically create one or more careers such as “Artificial Intelligence,” “Data and Analytics,” or “AI Engineering.” Navigate to Library > Careers in the left sidebar. Select + New Career to open the career creation form. Enter a career name (for example, Artificial Intelligence ) and a description that summarizes the scope of skills covered. Select Save . Tip: Consider creating separate career paths for different AI audiences — for example, “AI Literacy for All Employees” for general workforce skills and “Applied AI Engineering” for technical teams. This allows you to tailor skill depth and assessment expectations to each audience. ​ Define sections and skills Within each career, organize skills into logical sections. Sections help employees and managers navigate a large skill set by grouping related competencies together. Common sections for an AI transformation career might include: Section Example skills AI Fundamentals AI Literacy, Understanding Machine Learning, Responsible AI Generative AI Tools Prompt Engineering, ChatGPT, Copilot, Gemini Data Skills Data Interpretation, Working with AI Outputs, Evaluating Model Accuracy AI Governance AI Ethics, Bias Identification, Data Privacy in AI Systems | Applied AI | AI for Process Automation, AI-Assisted Decision Making | For each skill, navigate to Library > Skills and select + New Skill . Provide a clear name, a description that explains what the skill entails in practice, and link the skill to the relevant section in your AI career. ​ Set proficiency levels with grading rubrics A grading rubric defines what each level of proficiency means for a skill. Clear rubrics make assessments more consistent and help employees understand what they are working toward. Your organization’s administrator configures the grading scale (for example, a 1–5 or 0–7 scale). For each level, provide a short label and a detailed description. For AI skills, rubrics might look like: Level Label What it means 1 Awareness Can describe what AI is and give examples of AI tools in common use 2 Foundational Has used at least one AI tool; can identify appropriate use cases 3 Proficient Uses AI tools regularly in their role; can prompt effectively and evaluate outputs 4 Advanced Adapts AI tools to complex tasks; can guide others; understands model limitations 5 Expert Designs AI-integrated workflows; leads AI adoption efforts; coaches others Navigate to Company > Settings to configure grading rubrics. Once set, rubrics apply across all skills in your organization. ​ Phase 2: Baseline the Organization Who does this: Administrators and Employees Once your framework is in place, the next step is to understand where your workforce stands today. SkillsDB provides two complementary tools for establishing a baseline: surveys for gauging general AI readiness and sentiment, and self-assessments for capturing skill-level proficiency data. ​ Deploy an AI readiness survey Surveys let you ask open or structured questions to your entire organization or targeted groups. Before launching formal skill assessments, use a survey to gauge employee familiarity with AI tools, comfort level with AI adoption, and awareness of your organization’s AI strategy. Administrators create surveys in Company > Surveys . A readiness survey might include questions such as: “How familiar are you with generative AI tools such as ChatGPT, Gemini, or Copilot?” “How confident do you feel using AI tools in your current role?” “What barriers do you experience when trying to use AI tools at work?” Once deployed, survey responses are tracked and aggregated. Administrators can view response rates and results from the survey management interface. ​ Launch self-assessments Self-assessments ask employees to rate their own proficiency on the skills defined in your AI career framework. This gives you a self-reported baseline across the organization. Administrators launch assessment cycles from Company > Assessments . When a self-assessment cycle is a --- ## Expert Trainers URL: https://help.skillsdb.com/tutorials/expert-trainers Quick Summary: The Expert Trainer system lets your organization designate subject matter experts (SMEs) for specific skills. Employees submit training records directly to those experts for approval, creating a structured, peer-validated training workflow — with full visibility for managers and admins. ​ Overview Many organizations rely on internal subject matter experts to validate whether colleagues have genuinely developed a skill. SkillsDB formalizes this through the Expert Trainer system: a structured workflow that connects employees seeking training approval to the people best positioned to grant it. The system involves three roles working together: Administrators configure which skill flags carry trainer permissions and manage the overall setup. Managers (or admins) designate individuals as experts for specific skills, making them available as approvers. Employees submit training records for a skill and select an expert to review their submission. Expert Trainers receive approval requests in their Inbox, review the evidence, and approve or reject each submission. The result is a lightweight credentialing layer built entirely within SkillsDB — no external ticketing system required. ​ How the System Works The Expert Trainer workflow moves through five stages: Stage Who acts What happens 1. Configure Admin A skill flag is created with Trainer Permission enabled 2. Designate Manager / Admin The flag is applied to a person for a specific skill, designating them as an expert 3. Submit Employee Employee submits a training record and selects an expert approver 4. Approve Expert Trainer Expert reviews the submission in their Inbox and approves or rejects it 5. Monitor Manager / Admin Training Matrix and Trainer Metrics track approval status and response times The sections below walk through each stage in detail. ​ Stage 1: Configure the Trainer Flag (Admin) Before anyone can be designated as an expert trainer, an administrator must ensure a skill flag with Trainer Permission is active. SkillsDB may already have a suitable flag in place — confirm with your administrator before creating a new one. ​ Checking existing flags Navigate to Settings > Flags . Select the Skill Flags tab. Review the list of skill flags. Any flag with a purple Trainer badge already has Trainer Permission enabled. If one exists, skip to Stage 2. ​ Creating a new skill flag with Trainer Permission If no suitable trainer flag exists: Navigate to Settings > Flags and select the Skill Flags tab. Select Add Flag in the top right of the Skill Flags section. In the Add new skill flag dialog, enter: Flag name (required) — for example, Expert or Certified Trainer Description (optional) — a brief explanation of what this flag means in your organization Color (optional) — a visual identifier for the flag Select Save . The new flag card appears in the list. Locate the Trainer Permission checkbox on the flag card and check it. A confirmation message appears: “Trainer permission enabled successfully.” The flag card now displays a purple Trainer badge. Note: Only non-system flags can have Trainer Permission toggled. System default flags (marked with a blue System badge) cannot be modified. ​ Stage 2: Designate Expert Trainers (Manager / Admin) With a trainer-enabled flag in place, managers or administrators assign that flag to specific people for the skills they are qualified to approve. Once assigned, those people appear as selectable approvers when employees submit training requests for that skill. Expert flags can be applied at three levels: Skill level — designates someone as an expert for one specific skill Section level — designates someone as an expert for all skills within a section Career level — designates someone as an expert for all skills within a career Tip: Assigning the Expert flag at the career or section level is the most efficient approach for SMEs who are broadly qualified across a discipline. It automatically covers all underlying skills without requiring individual assignments. To assign an Expert flag, navigate to the team member’s profile or the Skills Matrix for your team and apply the appropriate flag. Contact your SkillsDB administrator if you need guidance on the flag assignment process for your organization’s specific setup. ​ Stage 3: Submit a Training Request (Employee) Once an expert has been designated for a skill, employees can submit training records for that skill and direct them to the appropriate approver. ​ Submitting training for a skill Navigate to the skill you want to submit training for. You can find skills through Search in the left sidebar or via your Skills Profile. Locate the My Trainings section on the skill page. Select Submit Training . The Submit Training modal opens. Complete the following fields: Field Required? Description Date of Training Yes The date the training or learning activity took place Text Evidence Depends on skill A written description of what you completed. Required only if the skill is configured to need it. SME Optional The expert who should review and approve this submission. Select from the dropdown — only people designated as experts for this skill appear here. Attachments Depends on skill Supporting files (certificates, completion records). Accepted formats: .jpg , .png , .pdf , .docx , .xlsx , .txt , .csv . Max 5 files, 10 MB each. Select Submit . A confirmation message appears: “Training submitted for approval.” Note: If no experts have been designated for a skill, the SME dropdown will be empty. Contact your manager or administrator to have an expert assigned before submitting. ​ Checking the status of your submission After submitting, you can monitor the status of your training request: Return to the skill page. In the My Trainings section, your submission appears with a Status badge: Pending — the expert has not yet reviewed your submission Approved — the expert approved your training record Rejected — the expert rejected your submission; you may resubmit --- ## Frontline Training URL: https://help.skillsdb.com/tutorials/frontline-training Quick Summary: SkillsDB Frontline Training capabilities help admins build a centralized training library, manage and approve employee training requests, track team training completion, and monitor trainer performance — all in one place. ​ Overview Frontline Training in SkillsDB is designed for organizations where structured, role-based training is central to operations — industries like manufacturing, healthcare, retail, logistics, and construction, where compliance, safety, and skills qualification are ongoing requirements. Rather than managing training records in spreadsheets or disconnected systems, SkillsDB gives admins a single platform to build a training library, review and approve training requests from employees, track who has completed what training and when, and measure how effectively your expert trainers are responding to requests. The Frontline Training workflow in SkillsDB involves several interconnected capabilities: Career Settings to enable training dates and timelines per career, the Training Library as the catalog of resources, Skill Flags with Trainer Permission to designate who can approve training, Training Suggestions for employee-proposed resources, Team Training views (All Activity, Training Matrix, Career Overview), the per-career Activity Log for audit and bulk actions, and Trainer Metrics for monitoring trainer responsiveness. Admins configure the setup; managers monitor progress; employees request and complete training through their own profile. Note: The Training Library must be enabled for your organization before these features are available. Contact your SkillsDB account manager or check Settings if you do not see training-related navigation items. ​ Prerequisites Before you begin configuring frontline training, ensure you have: Permission level: Administrator role in SkillsDB Feature enabled: Training Library enabled for your organization Setup requirement: At least one career and skill set created in SkillsDB (so training can be linked to roles) Access required: Library > Training , Settings > Training , and sidebar access to Training Approvals ​ Configuring Careers for Frontline Training Before the Training Library and training approvals become meaningful to a given group of employees, each career needs Training Dates enabled in its Career Settings. This is the switch that turns on training approvals, adds the career’s skills to the Training Matrix, and unlocks the per-career Career Overview dashboard. 1 Open Career Settings Navigate to Library > Careers and open the career you want to configure. Select Settings . 2 Enable Training Dates In the Measurement Model section, toggle Training Dates on. Additional controls appear: Training Timeline and the Bulk Update Skill Training Settings tool. 3 Set a Training Timeline Enter the expected duration for an employee to complete training across all skills in the career. Use any combination of Days , Months , and Years — for example, 6 months or 1 year 30 days. The timeline drives on-track / upcoming / overdue indicators on each employee’s career detail view. 4 Bulk-configure training settings on all skills Select Configure on the Bulk Update Skill Training Settings card. In the modal that opens, select the skills to update and set common values in one pass: Whether training is required for the skill Whether text evidence is required on submission Whether file attachments are required on submission Training expiration (days, months, years) after approval 5 Save Select Save Changes under the Measurement Model section. Note: Career Settings are per-career — each frontline career can have its own training timeline, evidence requirements, and expiration settings. See Career Settings for the full reference. ​ Setting Up Training Approval Authority Frontline training approvals are authorized through two levers: Default managers and administrators — always able to approve training for their scope. Skill Flags with Trainer Permission — any flag with the Trainer Permission toggle enabled grants approval authority to everyone who holds that flag for a given skill. SkillsDB ships with Expert as a system flag that has Trainer Permission enabled by default. If your organization wants a role like “Qualified Trainer” or “Line Lead” to sign off training without being a manager, configure a custom skill flag with Trainer Permission and apply it to the people in that role. To create a custom trainer flag: Navigate to Settings > Flags and select the Skill Flags tab. Select Add Flag . Enter a Flag Name (for example, Qualified Trainer ), optional description, and a color. After creation, toggle Trainer Permission on for the new flag row. Apply the flag to the appropriate people at the skill, section, or career level using the Flag People workflow from any career or skill page. Users who hold a Trainer-enabled flag receive the training approval requests in their Inbox and appear in the SME dropdown when employees submit training for those skills. See Skill Flags and Training Approvals for the full workflow. ​ Configuring Training Library Settings Before building out your training library, configure the metadata attributes that classify your training resources. These settings control the dropdown options available when creating or editing training entries. Navigate to Settings > Training to access Training Library Settings. The following attributes can be configured: Setting Purpose Example values Training Categories Classify the type of learning resource Course, Video, Article, Workshop Training Providers Identify the vendor or source Coursera, Internal L&D, Safety Board Training Formats Specify how training is delivered Online, In-Person, Hybrid, Self-Paced Target Audiences Define who the training is intended for All Staff, Supervisors, New Hires Course Levels Indicate difficulty or prerequisite level Beginner, Advanced, Expert To manage any attribute: Navigate to Settings > Training . Locate the attribute you want to configure (f --- ## Internal Recruiting URL: https://help.skillsdb.com/tutorials/internal-recruiting What you’ll learn: This tutorial walks through the complete internal recruiting workflow in SkillsDB — from searching for candidates with the right skills, to evaluating their proficiency against a target role, to tagging them for follow-up. No external ATS or spreadsheet required. ​ Overview When a role opens, the fastest and highest-quality hire is often already inside your organization. SkillsDB gives managers and HR teams the data to find that person systematically — using verified skill grades, benchmark comparisons, certifications, and learning progress rather than relying on who happens to be visible or well-connected. This tutorial covers the full workflow: Search for people with the skills your open role requires Filter the results by proficiency level, flag status, and organizational structure Evaluate individual candidates in depth using their full profile Compare candidates against the target role’s benchmark requirements Tag shortlisted candidates with people flags for tracking For managers: use the Skills Matrix to identify talent directly within your team Who this is for: Hiring managers, HR business partners, and senior leaders conducting talent reviews or succession planning. What you need: Manager or administrator access to SkillsDB. Employees do not have access to people search or team-level skill data. ​ Step 1: Search for Candidates by Skill The starting point for any internal recruiting workflow is the Search page. SkillsDB’s search covers the entire organization and lets you find people based on the skills they hold, the proficiency level they have demonstrated, and whether they have been recognized as an Expert in that skill. To search for candidates: Select Search from the left sidebar. In the filter bar beneath the search input, select People to focus the search on people rather than skills or training. Type the name of a key skill your open role requires — for example, Python , Financial Modeling , or Project Management . As you type, a suggestions dropdown appears. Select a skill from the suggestions to apply it as a structured filter, or press Enter to run a text search. SkillsDB runs the search and returns a ranked list of people who match your criteria. Each result shows the person’s name, the criteria that matched, and a Match Score — a percentage indicating how closely they aligned with your search. Tip: You do not need to know the exact skill name. Searching for a broad keyword like “data” or “cloud” returns all people linked to skills containing that term, then ranks them by relevance. ​ Step 2: Filter to the Right Candidates A broad skill search may return dozens of people. Use the filter panel to narrow results to those who are genuinely qualified for the role. To open the filter panel: Select Filters to the right of the search input. The filter panel expands below the search bar. ​ Filtering by skill proficiency These filters help you find people who have already reached the level your role requires — not just anyone who has the skill on their profile. Filter How to use it for recruiting Minimum Grade Set the lowest acceptable proficiency grade. For a senior role, set this to your organization’s equivalent of “Advanced” or “Expert.” People below this grade will be excluded. Skill Flags Select Expert to surface only people formally recognized as experts in this skill. Expert flags are applied by managers and administrators — they carry more weight than a self-assessed grade alone. Training Date Range Filter by when a person last completed training in this skill. Use “Last 12 months” to find people who are actively developing in the area. ​ Filtering by organizational structure These filters help you search across — or within — specific parts of the organization. Filter How to use it for recruiting Business Unit / Division Limit results to a specific business area, or broaden beyond your own team Department / Team Narrow to a department if the role requires familiarity with a specific function Country / City / Site Filter by location if the role has a presence requirement Job Title Find people already in adjacent roles who are ready to step up ​ Filtering by people flags If your organization uses People Flags to tag employees with designations like “High Potential” or “Ready for Promotion,” you can filter by these flags directly. Under the People Flags filter, select any flag to show only people who carry that tag. This is especially useful when an HR team or leadership group has already done a preliminary talent review. ​ Setting the filter match mode Below the filter panel, two match mode options control how filters combine: Match all — A person must meet every filter you have set. Use this for strict qualification screening. Match any — A person needs to meet at least one filter. Use this for broader talent discovery when you want to see a wider pool first. For a real recruiting search, Match all is usually the right choice once you have set precise filters. ​ Step 3: Review Search Results After applying filters, the results table shows only the people who meet your criteria. Each row includes: Column What it tells you Name The person’s full name — select to view their profile Match Score A percentage showing how closely they matched all your criteria. 100% means they satisfied every filter. | Matched Criteria | Tags showing exactly which parts of your search this person matched — for example, “Expert flag,” “Grade ≥ 3,” “Engineering” | Sort the table by Match Score (highest first) to prioritize the strongest candidates. People with scores above 80% are typically worth a closer look. ​ Step 4: Evaluate a Candidate’s Full Profile Select a person’s name to open their individual profile. This is where you move from “they match on paper” to a genuine assessment of their readiness and trajectory. ​ Overview tab The Overview tab shows the person’s current career path assignments, the number of skills they hold, and any highlights or additional skills beyo --- ## Partner Certification URL: https://help.skillsdb.com/tutorials/partner-certification Quick Summary: This tutorial walks through the full SkillsDB workflow for managing partner and industry certifications — covering admin setup, employee submission, manager approval, and ongoing tracking. Use it as an end-to-end reference for any external certification program your organization needs to track. ​ Overview Partner certifications are credentials issued by third-party technology vendors and industry bodies — such as AWS, Microsoft Azure, Salesforce, CompTIA, or Google Cloud — that employees earn and your organization needs to track and verify. These certifications are often required for maintaining vendor partnerships, qualifying for project work, or demonstrating team capability to clients. SkillsDB provides a structured workflow for managing partner certifications from end to end. Admins define the certifications in a shared library, assign them to employees who need to hold them, employees submit their credentials with supporting evidence, and managers review and approve each submission. The result is a verified, auditable record of who holds what credentials — and when they expire. This tutorial covers the complete workflow in the order it happens: Admin setup — creating certifications and certification types in the library Assignment — assigning certifications to employees Employee submission — submitting credential details and evidence Manager approval — reviewing and approving submissions Renewal — keeping certifications current as they expire Tracking and reporting — monitoring compliance across the organization ​ Step 1: Set up Certifications in the Library (Admin) Before certifications can be tracked, an administrator must create them in the SkillsDB certification library. This is a one-time setup step for each certification your organization wants to manage. ​ Create certification types Certification types are used to group certifications by vendor or category — for example, “AWS”, “Microsoft”, “Salesforce”, or “CompTIA”. Creating types first makes it easier to organize the library and filter results later. Navigate to Library > Certifications Select Manage Types in the top right In the Manage Types drawer, select + Add Type Enter a Name for the type (for example, AWS , Microsoft Azure , or CompTIA ) Add an optional Description Select Save Repeat for each vendor or category your organization tracks. ​ Add certifications to the library With types in place, create the individual certifications employees will be assigned. Navigate to Library > Certifications Select + Certification Fill in the certification details: Name (required): The full certification name, for example AWS Certified Solutions Architect – Associate Type (required): Select the appropriate vendor type from the dropdown Issued By (optional but recommended): The issuing authority name, for example Amazon Web Services URL (optional): A link to the certification’s official page or verification portal Description (optional): A brief description of what the certification covers Select Save The certification now appears in the library and is available for assignment. Tip: Including the Issued By name and URL adds important context for managers reviewing submissions. The URL makes it easy to cross-reference credentials against the issuing authority’s verification portal. ​ Step 2: Assign Certifications to Employees (Admin or Manager) Once certifications exist in the library, they must be assigned to the employees who need to hold them. Assigned certifications appear in each employee’s My Certifications page with a status of Assigned , signaling that they need to submit their credentials. ​ Assign from the library Navigate to Library > Certifications Locate the certification you want to assign Select the Assign icon (person with a plus sign) on the certification row Search for and select the employee to assign it to Confirm the assignment The employee immediately sees the certification in their profile with a Submit Details prompt. Note: Certifications are assigned one employee at a time. If you need to assign the same certification to a large group, repeat the process for each person or contact your SkillsDB account manager about bulk assignment options. ​ Step 3: Submit Certification Details (Employee) When an employee has earned a partner certification, they submit their credential details through SkillsDB. This kicks off the approval workflow. ​ Find and open the assigned certification Select Certifications from the left sidebar The My Certifications page lists all certifications assigned to you Locate the certification with the Submit Details status indicator Select the certification row to open the detail page ​ Fill in the submission form On the certification detail page, select Submit Details Complete the submission form: Issued Date (required): The date the certification was granted or passed Expiration Date (optional): The date the certification expires, if applicable ID Number (optional): Your credential or license number from the issuing authority — for example, AWS-12345 or AZ-900-XYZ Attachments (optional): Upload supporting documents such as your certificate PDF, digital badge, or course completion record Select Submit Your certification status changes to Awaiting Approval and your manager receives a notification to review your submission. Tip: Include your ID Number and at least one attachment with every submission. Managers are much faster to approve when they have the credential number to reference and a certificate to verify against. Attachment rules: You can upload up to 5 files per submission. Accepted file types are .jpg, .png, .pdf, .docx, .xlsx, .txt, and .csv. Each file must be under 10 MB. ​ What happens after submission Once submitted, your certification is locked for editing while it is under review. You can see the current status — Awaiting Approval — on your My Certifications page. When your manager approves or denies the submission, the status updates and you can see the outcome --- ## Quality Management URL: https://help.skillsdb.com/tutorials/quality-management Quick Summary: This guide walks through how to use SkillsDB as an end-to-end quality management system — from setting up your compliance framework to tracking certifications, running assessments, managing training records, and generating audit-ready reports. ​ Overview Quality management in a regulated industry depends on one thing above all else: knowing that the right people have the right credentials, competencies, and training — and that you can prove it. SkillsDB is designed to give quality managers, HR teams, and frontline supervisors a single platform to manage all of that in one place. This tutorial walks through the full quality management lifecycle in SkillsDB. It covers five core workflows — certification compliance, competency assessments, training records, skill gap closure, and compliance reporting — and explains how each role in your organization uses the platform to keep your workforce audit-ready. SkillsDB supports quality-focused organizations in industries including manufacturing, healthcare, life sciences, food production, logistics, and any environment where workforce competency and compliance documentation are regulatory requirements. ​ Who This Guide Is For This tutorial is written for three audiences: Role Primary Use Administrators Configure the system, manage certification and training libraries, define job roles and skill benchmarks, import and assign credentials at scale Managers Assign certifications and training, assess team competency, approve submissions, monitor compliance status, close skill gaps Employees Submit certification evidence, complete assessments, track training progress, and build learning plans The sections below are organized by workflow. Each section calls out which roles are involved and what actions each can take. ​ Step 1: Build Your Quality Compliance Foundation Before tracking compliance, your administrators need to configure SkillsDB to reflect your organization’s structure and requirements. Think of this as defining the rules your workforce needs to comply with. ​ Define your job roles and skill requirements Job roles in SkillsDB link positions to the specific skills and proficiency levels required to perform them. When roles are configured correctly, SkillsDB can automatically calculate skill gaps and surface compliance shortfalls. What administrators do: Navigate to Library > Careers in the left sidebar. Create a career (job role) for each position in your organization (for example, “Quality Inspector,” “Line Supervisor,” “QA Auditor”). Add skills to each role with a benchmark grade — the minimum proficiency level required for that role on your organization’s grading scale. Once roles are configured, assign your employees to the appropriate job role in their people profile. SkillsDB then uses that role to calculate each person’s skill gap automatically. Note: Your grading scale (for example, 1–5 or Beginner–Expert) is configured by your administrator in Settings > Grading . All benchmark and assessment grades are based on this scale. ​ Build your certification and training libraries Your certification and training libraries are the master records your team works from. Admins create entries here; managers and employees interact with them throughout the compliance cycle. What administrators do: Navigate to Library > Certifications and add each required certification — for example, “Forklift Operator License,” “ISO 9001 Lead Auditor,” or “Food Handler’s Permit.” Navigate to Library > Training and add training courses your organization uses — including training provider, format (online, in-person, hybrid), and course level. Tip: Use consistent naming conventions from the start. If your certifications and training records are imported from another system, SkillsDB supports bulk CSV import. Navigate to Import in the left sidebar to upload existing records. ​ Step 2: Assign and Track Certifications Certification tracking is the backbone of most quality compliance programs. SkillsDB manages the full lifecycle: assigning requirements, collecting evidence, processing approvals, tracking expiration dates, and flagging renewals. ​ How certification statuses work Every certification assigned to an employee moves through the following stages: Status What it means Assigned The certification is required; the employee sees a Submit Details button Awaiting Approval The employee submitted their evidence; a manager or admin reviews it Approved The submission was accepted; the certification is active Denied The submission was rejected; the employee must resubmit Expiring Soon The certification expires within 30 days Expired The certification’s expiration date has passed ​ Assigning certifications to your team Managers and administrators assign certifications from an employee’s profile. Navigate to People (from the Team section in the left sidebar) and select the employee. Go to the Certifications tab on their profile. Select Assign Certification and choose the relevant certification from your library. To assign certifications to large groups at once, use the Import function in the left sidebar. A CSV import lets you assign certifications to hundreds of employees in a single step, which is particularly useful when onboarding a new team or rolling out a compliance initiative. ​ How employees submit certification evidence When an employee has been assigned a certification, they navigate to Certifications in the left sidebar under the Profile section. Their page shows all assigned certifications. The employee selects the certification with Assigned status. They select Submit Details . They fill in the certification details — including the issuing authority, ID or license number, issue date, and expiration date. They attach supporting documentation (up to 5 files; accepted formats: .jpg, .png, .pdf, .docx, .xlsx, .txt, .csv; maximum 10 MB per file). They submit for approval. The status changes to Awaiting Approval and a notification appears in the manager’ --- ## Resource Planning URL: https://help.skillsdb.com/tutorials/resource-planning Quick Summary: Resource planning in SkillsDB means using your organization’s skill data to answer questions like: Who has the skills for this project? Where are our biggest gaps? How do we close them? This tutorial walks through the full workflow — from assessing your team’s current state to finding the right people and building development plans. ​ Overview Resource planning is the practice of matching your organization’s skill capacity to its needs. Before you can staff a project effectively, make a hiring decision, or prioritize a training initiative, you need to know what skills your team currently has, where the gaps are, and who is best positioned to fill them. SkillsDB gives you a connected set of tools to do exactly that. Rather than relying on spreadsheets or informal knowledge, you can use real assessment data, benchmark comparisons, and skills matrices to make resourcing decisions on a solid foundation. This tutorial covers the end-to-end resource planning workflow: Assess your team’s current skill state — understand who has what, at what level, across your organization’s defined Careers Identify gaps and strengths — use the Skills Matrix and Career Overview to pinpoint where capacity is thin and where it’s strong Find the right people — use Find Experts to search for individuals with specific skills across your organization Build upskilling plans — use Learning Plans to close gaps and track development progress Monitor training coverage — use the Training Matrix to confirm skills are being trained and certifications are current Resource planning in SkillsDB is primarily used by managers, directors, executives, and administrators. Employees can view their own skills data and learning plans, but the team-level analytics described here require manager-level access or higher. ​ Prerequisites Before following this tutorial, confirm that: Your organization has defined Careers (role definitions with skills and benchmark grades) in SkillsDB Employees have been assigned to Careers by a manager or administrator Assessments have been completed so that skills have recorded grades to compare against benchmarks You have manager-level access or higher to view team skills data If Careers have not been configured or assessments have not been run, contact your administrator before proceeding. The skills data in SkillsDB is only as useful as the assessment coverage behind it. ​ Step 1: Get an Overview of Your Team’s Skill Coverage The starting point for resource planning is understanding how your team’s skills are distributed across the Careers you manage. ​ Navigate to Team Skills Select Skills from the left sidebar navigation under the Team section. The My Team Skills page opens, showing a consolidated summary of your team’s skills organized by Career. ​ Understanding the My Team Skills table The table is organized into three sections: Row What it shows All Careers The total number of people assigned across all Careers and the total number of skills in scope Highlights Skills that have been flagged as highlighted — useful for tracking key or critical skills Additional Skills Skills that people on your team have recorded outside their assigned Career — breadth beyond their defined role Below these rows, a collapsible Careers group lists each Career assigned to your team. For each Career, the table shows: People Assigned — how many people in your team hold this Career Skills — how many skills are attached to this Career definition Select any Career row to open the Career Overview for that role and see a deeper breakdown of skill coverage, proficiency distributions, and performance rankings. ​ Scoping to direct reports or your full org If you manage a large or multi-level team, you can scope the view: By default, the page shows your full reporting organization — everyone who reports to you, directly or indirectly. Administrators can toggle Direct Reports in the filter bar to limit the view to their immediate direct reports only. ​ Step 2: Analyze Skill Coverage for a Specific Career Once you’ve identified a Career you want to examine, select it to open the Career Overview page. This page gives you a visual and data-driven breakdown of skill health for that role across your team. ​ The Career Overview stats bar At the top of the Career Overview, a stats bar shows key metrics for this Career: Metric What it tells you Total People How many people in your organization are assigned to this Career Total Assign How many people have grades recorded in the Skills Matrix Total Skills How many skills are defined in this Career Meets Target The percentage of skill grades that meet or exceed benchmark Below Target The percentage of skill grades that fall below benchmark — your skill gap rate Training Resources How many learning resources are linked to this Career | Skills w/ Training | What percentage of skills in this Career have at least one linked training resource | A high Below Target percentage signals that a significant portion of your team’s skills are below the expected proficiency level for this role. A low Skills w/ Training percentage means that many skill gaps don’t have a training path defined — a signal to work with your administrator on adding learning resources. ​ The Career Overview charts Below the stats bar, the Career Overview displays several charts and tables to help you understand skill health at a glance: Beeswarm Chart — shows the distribution of average skill levels across your team, visualizing clustering and outliers Bar Chart — compares manager-assessed grades to employee self-assessed grades by skill, useful for identifying perception gaps Skills Matrix preview — a condensed grid of skills versus people with color-coded grades; select Full Report to open the complete Skills Matrix People ranking — your team members ranked by average skill grade; toggle between Top and Bottom to identify your strongest contributors and those who may need the most development support Skills ranki --- ## Talent Development URL: https://help.skillsdb.com/tutorials/talent-development Quick Summary: This guide walks administrators through the end-to-end setup required to use SkillsDB for talent development. Follow the steps in order: configure your grading scale, enable features, build your Skills Library, create Careers, assign employees, run assessments, add learning resources, and monitor results. ​ Overview SkillsDB’s talent development capability gives your organization a structured way to define what skills are expected in each role, measure where employees currently stand against those expectations, and support their growth through targeted learning. Rather than relying on informal conversations or disconnected spreadsheets, SkillsDB brings skills data, assessments, benchmarks, and learning plans together in one place. This getting started guide covers the administrator setup required to activate talent development for your organization. By the end of this guide, your employees will have assigned Careers that define their skill expectations, assessment grades recorded against benchmarks, and access to learning resources linked to their development areas. The talent development workflow in SkillsDB follows a clear sequence: Configure your grading scale — define the proficiency levels used across your entire organization Enable the features you need — turn on libraries, flags, and notifications in Settings Build your Skills Library — create the skills your organization tracks Create Careers — define role structures with skills, sections, benchmarks, and settings Assign employees to Careers — connect people to the roles that apply to them Run an assessment cycle — collect self and manager grades to populate skill data Add learning resources — link training content to skills and Careers Monitor and act — use analytics to track coverage, gaps, and progress Administrators have access to all setup steps described here. Some steps — such as assigning employees to Careers and running team assessments — can also be performed by managers within their reporting structure. ​ Prerequisites Before setting up SkillsDB for talent development, confirm that: You have Administrator access to your SkillsDB organization Your organization’s employee records have been created or imported into SkillsDB (either manually via Team > People or via the Import tool) You have an understanding of the roles, levels, and skills used in your organization — this will be the foundation for building Careers If employees have not yet been added to SkillsDB, complete that step first. See Viewing Your Team for details on how people records are structured. ​ Step 1: Configure Your Grading Scale The grading scale defines the proficiency levels used across your organization for all skill assessments. Every grade badge, benchmark, and gap calculation in SkillsDB uses this scale, so it should be configured before you create skills or run assessments. SkillsDB supports a fully customizable grading scale. Each grade has a numeric value, a short description, and an optional detailed description. For example, a five-point scale might use: 1 - Awareness , 2 - Developing , 3 - Proficient , 4 - Advanced , 5 - Expert . To configure your grading scale: Select Settings from the left sidebar under the Company section. Locate the Grading Scale section and select the link to open the grading settings page, or navigate directly to Settings > Grading Scale . Review the existing grades. Each row shows the grade number, short description, and detailed description. To edit a grade, select the field you want to change and type a new value. Changes are saved automatically. To add a new grade, select Add Grade and enter the grade number, short description, and an optional detailed description. To remove a grade that is no longer needed, select the delete icon on that row. Grades that have been used in existing assessments or benchmarks cannot be deleted. Important: Your grading scale affects every assessment, benchmark, and skills matrix across your entire organization. Changing grade values or removing grades after assessments have been completed will affect historical data and benchmark comparisons. Define your grading scale before running your first assessment. ​ Step 2: Enable Features in Settings SkillsDB has a set of company-wide settings that control which features are available to your users. Review and configure these before proceeding with your talent development setup. To access settings: Select Settings from the left sidebar under the Company section. The Settings page displays all available configuration options. The key settings for talent development are: Setting What it controls Hide Manager Grades When enabled, employees cannot see their manager’s assessment of their skills. Enable this if you want managers to complete their assessments before employees see the results Skill Flags Enables Focus, Expert, and Mentor flags on skills. Enable this if you want managers to highlight key skills or designate subject-matter experts System Emails Enables or disables automated notification emails sent to employees and managers (for example, assessment start notifications and nudges) Library: Skills Makes the Skills Library visible and usable. Must be enabled to create and manage skills Library: Careers Makes the Careers library visible and usable. Must be enabled to create and manage Careers Library: Training Makes the Training library visible. Enable this to link learning resources to skills and Careers Library: Certifications Makes the Certifications library visible. Enable this if your organization tracks professional credentials | Date Assigned | Controls whether employees and managers can see when skills or assessments were assigned to them | Enable the Library settings for Skills, Careers, and Training as a minimum for the talent development use case. Toggle each switch to the desired state — changes are saved immediately. ​ Step 3: Build Your Skills Library The Skills Library is the master list of skills your organi --- ## Workforce Strategy URL: https://help.skillsdb.com/tutorials/workforce-strategy Quick Summary: This tutorial walks executives and senior leaders through the full SkillsDB workflow for workforce strategy — from assessing your organization’s current skill health and surfacing critical gaps, to tracking certification compliance, monitoring training coverage, and exporting data for leadership reporting. ​ Overview This tutorial is designed for executives, senior leaders, and HR leaders who need a strategic, organization-wide view of workforce capabilities. This includes roles such as Chief People Officers, VPs of Talent, Directors of Learning & Development, and any leader responsible for making decisions about workforce readiness, skills investment, or talent strategy. SkillsDB surfaces the quantitative data behind your workforce — proficiency levels, skills gaps, training coverage, certification compliance, and expert distribution — so leaders can move from gut-feel to evidence-based decisions. By the end of this tutorial, you will know how to: Get a real-time picture of your organization’s skill health Identify where critical gaps exist between current capabilities and role requirements Locate your subject-matter experts and high performers Track certification compliance across the organization Review training coverage by team, role, or skill Monitor assessment participation and completion Export clean data for board presentations, planning cycles, or HR reviews ​ Prerequisites To access organization-wide data in SkillsDB, you need: Admin access — Company-wide skills, training, and certification data requires the appropriate administrator-level permissions. If you have a Manager role, you will see data scoped to your direct reports and your organizational hierarchy (“My Org” view). Contact your SkillsDB administrator to confirm or adjust your access level. Skills data entered — The analytics in SkillsDB are only as rich as the underlying data. At minimum, your organization should have job roles (careers) defined with skills mapped, and at least one completed assessment cycle. Many executives use this tutorial as a prompt to confirm data completeness before drawing conclusions. Note: If your organization is still in the early stages of SkillsDB setup, the most valuable first step is ensuring your career library and skills framework are complete. See Careers and Skills in the Admin Guide. ​ Step 1: Assess Your Organization’s Skill Health The first question any workforce strategy starts with is: What skills does our organization have right now? SkillsDB answers this through skills analytics tied to your job role library. ​ View skills health by career A career in SkillsDB is a job role — for example, “Software Engineer” or “Operations Manager.” Each career has skills mapped to it with benchmark proficiency levels. The Career Overview shows you how your people measure against those benchmarks. Navigate to Library > Careers from the left sidebar. Select a career to open its detail page. Select the Overview tab. The Overview tab displays: Metric What it tells you Average grade The mean proficiency across all people in this role On target Count of people meeting or exceeding benchmark for each skill Skill gaps Count of people below benchmark | Top performers | People with the highest average manager-assessed grades | | Bottom performers | People with the most development opportunity | | Proficiency distribution | A visual chart showing how grades are spread across the skill | The bar chart on the Overview tab compares employee self-assessed grades, manager-assessed grades, and the role’s benchmark — all in a single view. When self-grades and manager grades diverge significantly, that is often a signal worth exploring in a deeper conversation with that team’s manager. ​ View skill-level analytics For any individual skill, you can drill into how your entire organization performs on that competency: Navigate to Library > Skills from the left sidebar. Select a skill to open its detail page. Select the Analytics tab. The Analytics tab breaks down performance by division, department, team, and job role — so you can see whether a skills gap is isolated to one part of the business or systemic across the organization. Tip: Use the department breakdown chart to identify whether a skills gap is concentrated in one area or distributed org-wide. A gap in one department suggests a training delivery problem. A gap across all departments suggests a hiring, compensation, or industry-wide issue. ​ Step 2: Identify and Prioritize Skills Gaps Knowing you have gaps is the first step. Knowing which gaps are most critical — and what their magnitude is — is what drives investment decisions. ​ Use the skills matrix to see coverage at a glance The skills matrix for a career shows every person in that role mapped against every skill, with their proficiency level color-coded against the benchmark. This is the most effective single view for identifying coverage patterns. Navigate to Library > Careers from the left sidebar. Select a career. Select Skills Matrix from the career’s navigation tabs. The matrix displays people as rows and skills as columns. Each cell shows that person’s proficiency grade with a color indicator: Green — At or above benchmark Yellow — Approaching benchmark Red — Below benchmark Empty — Not yet assessed When you see a column with predominantly red or empty cells, that is a high-priority skills gap — a competency your role requires that your team broadly lacks. When you see a row with predominantly red cells, that is an individual development opportunity. ​ Prioritize gaps by business impact Not all gaps carry equal risk. Prioritize by asking: Which skills are on the critical path for upcoming projects or business goals? Which gaps affect the most people (wide gaps vs. deep individual gaps)? Which skills have no internal experts — meaning there is no one to train others if someone leaves? Use the Skill Overview page (Library > Skills > [Skill]) to check the Experts and Mentors co --- ## Building a Learning Plan URL: https://help.skillsdb.com/user-guide/building-a-learning-plan Quick Summary: Your Learning Plan is where you track all learning resources assigned to you or added by yourself. You can move resources through four stages — To Do, In Progress, Completed, and Archived — log your progress, add custom resources, and export your plan. ​ Overview Your Learning Plan in SkillsDB is a personal workspace for managing all of the learning resources connected to your development. It brings together everything assigned to you by your manager or tied to your career, alongside resources you add yourself, in one organized view. Learning plans are most useful when you are actively working toward closing skill gaps, preparing for a new role, or completing development goals agreed on with your manager. Resources appear in your plan when your manager or an administrator assigns them to you, when they are linked to a Career you have been assigned to, or when you add them yourself from the learning library or as a custom entry. All employees can view and manage their own Learning Plan. You do not need any special permissions to access this page or to update your progress on assigned resources. Managers and administrators can view your learning plan and assign resources to it; your manager can also add and update resources on your behalf. There are two types of items in your Learning Plan: Library resources — resources that come from the SkillsDB learning library. These may be assigned to you by your manager, linked to your Career, or added by you directly from the library. Library resources include a title, description, category, and optional link. Custom resources — resources you create yourself by entering a title and details. Custom resources are useful for tracking learning that is not yet in the library, such as an internal training session, a book, or an external course not included in your organization’s library. ​ Navigating to Your Learning Plan To view your learning plan: Select Learning Plan from the left sidebar navigation. The My Learning Plan page opens in Board view by default, showing your learning resources organized into four columns. ​ Understanding the Board View By default, your learning plan is displayed as a board — a Kanban-style layout with four columns representing the stages of your learning activity. Column Meaning To Do Resources assigned to you that you have not yet started In Progress Resources you are actively working through Completed Resources you have finished Archived Resources you have set aside and are no longer actively pursuing Each card on the board shows the resource title, description, category badge, labels, who added it, and your current rating (for library resources). To move a resource between columns, drag and drop the card to the target column. Not all moves are permitted — the board enforces a logical progression: To Do can move to In Progress or Archived. In Progress can move to Completed or Archived. Completed can only move to Archived. Completion cannot be undone by moving a card back. Archived can move back to In Progress. Note: If you try to drag a card to a column that is not a valid next step, the board will return the card to its original position. ​ Understanding the Table View The table view shows your learning plan as a grouped list, organized by status. To switch to the table view: Select Display in the top right of the page. Select Table . In the table view, resources are grouped under their current status heading (To Do, In Progress, Completed, Archived) and sorted in that order. Each row shows: Column Description Learning Plan The resource name and description Labels Any labels applied to the resource Category The resource type or category (such as Course, Video, or Article) Added by The name of who added the resource and when Rating Your thumbs rating for the resource (library resources only) The table view is also the mode used when exporting your learning plan. ​ Understanding Item Statuses and Allowed Transitions Each item in your Learning Plan has a status that reflects your progress. Status changes follow a set progression and cannot be reversed in all directions. Status Description Can transition to To Do Not yet started In Progress, Archived In Progress Actively being worked on Completed, Archived Completed Finished Archived only Archived Set aside — no longer active In Progress Once an item is marked Completed, it cannot be moved back to In Progress or To Do. If you need to re-engage with a completed resource, archive it first and then restart it from Archived. ​ Adding a Custom Resource You can add resources to your learning plan that are not in the SkillsDB learning library. Custom resources are useful for tracking personal learning activities, external courses, books, internal workshops, or any development activity you want to log. To add a custom resource: Select Add resource in the top right of the page. In the Add new learning modal, complete the following fields: Title (required) — The name of the resource. Description — A brief description of the resource. Category (required) — The type of resource, such as Course, Video, or Article. Select from the available categories configured by your organization. URL — A direct link to the resource. The URL must begin with http:// , https:// , or www. . Duration — The estimated time to complete the resource, in hours. Must be greater than 0 if provided. Select Add resource . When you submit, the new custom resource is added to the To Do column of your learning plan. Tip: Use the URL field to link directly to the course or material so you can open it from your learning plan card with a single click. ​ Updating Your Progress You can log your duration and progress percentage for any resource in your learning plan — both library resources and custom resources. To update your progress: On the resource card in the board view, open the card’s action menu (the three-dot icon or the action button on the card). Select Update . In the Update duration and progress --- ## Managing Certifications URL: https://help.skillsdb.com/user-guide/managing-certifications Quick Summary: Your Certifications page shows all certifications assigned to you by your manager or administrator. From here you can submit your certification details for approval, renew credentials when they expire, and view the full history of each certification. ​ Overview Certifications in SkillsDB represent your professional credentials — licenses, qualifications, and formal certifications that are relevant to your role. Your organization uses SkillsDB to track which certifications you hold, when they were issued, and when they expire. Certifications are assigned to you by your manager or an administrator. Once a certification is assigned, you are responsible for submitting the details — such as your issued date, expiration date, credential ID, and any supporting documents. Your manager or administrator then reviews and approves your submission. All employees can view and manage their own certifications. You do not need any special permissions to view your Certifications page or submit certification details. However, you cannot add certifications to your own profile — certifications must be assigned to you by a manager or administrator. Note: If you believe a certification should appear in your list but it does not, contact your manager or administrator to have it assigned to you. ​ Navigating to Your Certifications To view your certifications: Select Certifications from the left sidebar navigation. The My Certifications page displays a table of all certifications assigned to you. ​ Understanding the Certifications Table The My Certifications table shows key information about each certification at a glance. Default columns: Column Description Certification The certification name. Select any row to open the certification detail page. Status The current status of your certification (see Understanding certification statuses below). Expires The expiration date with a visual indicator: Expired (red), Expiring Soon (within 30 days, amber), Valid (green), or No Expiration. Type The certification type or category, as configured by your organization. Files The number of supporting documents attached to the certification. Additional columns (hidden by default, enable via the column chooser): Column Description Labels Any labels applied to the certification. Issued Date The date the certification was first granted. ID Number Your credential ID or certification number. Authority The name of the issuing organization. To show or hide columns, select the Display button in the top right of the page. ​ Understanding Certification Statuses Each certification has a status that reflects where it is in the review process. Status Displayed as Meaning Assigned Submit Details The certification has been assigned to you. You need to submit your details for approval. Awaiting Approval Awaiting Approval You have submitted your details and are waiting for your manager or administrator to review. Approved Approved Your manager or administrator has approved your certification details. Denied Denied Your manager or administrator has rejected your submission. You can resubmit updated details. Expired Expired Your certification has passed its expiration date. You can renew it to submit new details. Modified Modified The certification details have been updated after a previous approval. ​ Submitting Certification Details When a certification is assigned to you, its status displays as Submit Details . You must submit your certification details before your manager or administrator can approve it. To submit your certification details: Select Certifications from the left sidebar navigation. In the table, select the row of the certification with Submit Details status. This opens the certification detail page. On the detail page, you will see a yellow alert: Certification Assigned — Please add details to your assigned certification . Select Add Details . In the Add Certification Details modal, complete the following fields: Issued Date (required) — The date you were first granted this certification. Expiration Date — The date the certification expires. Leave blank if the certification does not expire. The expiration date must be after the issued date. ID Number — Your credential ID or certification number. This field accepts letters, numbers, and hyphens only. Attachment — Upload supporting documents such as your certificate, transcript, or badge. You can upload up to 5 files. Accepted formats: .jpg, .png, .pdf, .docx, .xlsx, .txt, .csv (maximum 10 MB per file). Select Submit . When you select Submit, your certification status changes to Awaiting Approval . Your manager or administrator will review your submission and either approve or deny it. Tip: Attach your official certificate document when submitting details. This gives your manager or administrator the supporting evidence they need to approve your submission quickly. ​ Viewing Certification Details and History The certification detail page shows the full record for a single certification, including the current status, metadata, and a history of all previous submissions and renewals. To open the certification detail page: Select Certifications from the left sidebar navigation. Select any row in the table to open that certification’s detail page. The top section of the detail page displays: The certification name and description Metadata badges: Type , Issued by (the issuing authority name), and a link to the issuing authority’s website if one is recorded Contextual action buttons based on the current status (such as Renew ) The history table below shows a row for each submission or renewal: Column Description Status The outcome of this submission (Approved, Denied, etc.) Requested The date you submitted this set of details for approval Approved The date the submission was approved Expires The expiration date recorded in this submission Issued The issued date recorded in this submission Certification ID The credential ID or certification number for this submission App --- ## Responding to Surveys URL: https://help.skillsdb.com/user-guide/responding-to-surveys Quick Summary: Surveys are questionnaires assigned to you by your manager or administrator. This article explains how to find, complete, and submit surveys in SkillsDB. ​ Overview Surveys in SkillsDB are structured questionnaires that your organization uses to gather information about skills, development needs, certifications, and other workplace topics. When a manager or administrator creates a survey and assigns it to you, it appears in your personal survey list for you to complete. Surveys can contain a variety of question types — from simple yes/no questions to rating scales, open-ended text responses, and file uploads. Some questions are required and must be answered before you can submit the survey. Others are optional and can be skipped. Your responses are saved automatically as you move between questions, so you can pause and return to a survey at any time without losing your progress. Once you submit a survey, you can view your responses but cannot edit them. ​ Prerequisites Before responding to a survey, you need: Access requirement : A SkillsDB user account Setup requirement : At least one survey assigned to you by a manager or administrator Standard users cannot create or assign surveys. Surveys are created and assigned by managers and administrators only. ​ Understanding Your Surveys Select Surveys from the left sidebar to open the My Surveys page. This page displays all surveys that have been assigned to you. At the top of the page, status filter chips let you quickly filter your surveys: All — shows every survey assigned to you Not Started — surveys you have not yet opened In Progress — surveys you have started but not submitted Completed — surveys you have submitted Past Due — surveys whose due date has passed without submission Each survey in the list shows the following information: Column Description Survey Name The title of the survey Status Your current progress on the survey (see status definitions below) Due Date The date by which the survey should be completed Completion Date The date you submitted your responses (populated after submission) Action The button that opens the survey — Start , Continue , or View Response ​ Survey statuses Status Meaning Not Started The survey has been assigned to you but you have not yet opened it In Progress You have started the survey but have not yet submitted your responses Completed You have submitted all required responses Past Due The due date has passed and the survey has not been completed ​ How to Respond to a Survey Step 1: Open the survey Select Surveys from the left sidebar Locate the survey you want to complete in the My Surveys list Select the action button to open the survey: Start — appears when the survey status is Not Started Continue — appears when the survey status is In Progress or Past Due The survey opens and displays the first unanswered question. The top of the screen shows the survey name, your current progress as a percentage, and your position in the survey (for example, “Question 1 of 8”). Step 2: Navigate through questions Surveys open one question at a time. Use the following controls to move through the survey: Select the right arrow in the footer, or press Enter , to save your current response and advance to the next question Select the left arrow in the footer to return to the previous question Select the × in the top right to close the survey and return to the My Surveys page A progress bar runs across the top of the screen, and the header shows the survey name followed by your position — for example, 2 of 9 . The same counter appears above the question title. The footer shows the hint Press Enter ↵ to continue . Note: Your response is automatically saved each time you move to a different question. If you close the survey and return later, your answers are preserved. If a required question is unanswered, the forward arrow does not advance and the message This question requires a response appears above the footer. Optional questions can be skipped. Step 3: Answer each question Answer each question using the input method provided. Required questions are marked with a red asterisk ( * ) after the question title and must be answered before you can submit the survey. Questions without an asterisk are optional and can be left blank. The following question types may appear in a survey: Question type How to answer Multiple choice Select an option. Each option is lettered — press the matching letter key to select it, or select the option directly. Drop down Select one option from the menu. The closed menu reads Choose an option… Text response Type your answer in the text field File upload Upload one or more files (see file requirements below) Confirm certifications Review and confirm or update your certification details. This type appears only when your organization has certification responses enabled. Note: Older surveys may also contain Rating , Yes/No , or Likert questions. These types still display and accept answers, but they are no longer offered when building a new survey. Note: Rating scales and other configurable question types may use different ranges depending on how your administrator has set up the survey. File upload requirements: Accepted formats: .jpg , .png , .pdf , .docx , .xlsx , .txt , .csv Maximum file size: 10 MB per file Maximum number of files: 5 per upload question Step 4: Review and submit After the last question, the review screen appears. It reads Ready to submit when everything required is answered, or N required questions remaining when something is outstanding, followed by a count of how many questions you answered. From the review screen, you can: Select Go back to return to the survey and change any responses Select Submit Survey to submit your responses Important: You cannot submit while required questions remain unanswered. The review screen tells you how many are outstanding — select Go back and answer them before submitting. When you select Submit Survey , SkillsDB saves --- ## Self Assessments URL: https://help.skillsdb.com/user-guide/self-assessments Quick Summary: A self-assessment is a structured evaluation where you grade your own proficiency across a set of skills. Completing a self-assessment updates your Employee grade in your Skills Profile and gives your manager and organization a view of your self-reported skill levels. ​ Overview A self-assessment is a formal evaluation cycle assigned to you by your manager or an administrator. During a self-assessment, you review each skill assigned to your role and grade your own proficiency using your organization’s grading scale (typically 1–5). You can also mark skills that do not apply to your role and flag skills you want to develop. Self-assessments exist to give employees a voice in how their skills are recorded. Rather than relying solely on manager observations, self-assessments capture your own view of your proficiency — which your manager and administrator can then compare against their own assessment and the role’s benchmark expectations. All employees can complete self-assessments when one is assigned to them. You do not need any special permissions to access or complete your self-assessment. Note: Self-assessments are assigned by your administrator or manager. You cannot create or initiate your own assessment cycle. If you believe you should have an active assessment but cannot see one, contact your manager or administrator. ​ Navigating to Your Assessments To view your active and completed assessments Select Assessments from the left sidebar navigation. The Assessments page shows all assessments assigned to you, with the following columns: Column Description Name The assessment title Deadline The date by which you must submit Status Your current progress (In progress, Completed, or Ended) Actions A button to continue, view the scorecard, or start the assessment An assessment shows Ended when your administrator has closed the assessment cycle. In this case, the action button shows Scorecard so you can view your results. If the assessment ended before you submitted, contact your administrator. Select any assessment row or its action button to open it. ​ Starting an Assessment When you open a new assessment for the first time, an intro modal appears to prepare you before you begin grading. Step 1: Keyboard shortcuts The first step of the intro modal shows the keyboard shortcuts available during grading. These shortcuts let you navigate and grade efficiently without using your mouse. Key Action 1 – 5 Assign a grade to the current skill N Toggle Not Applicable for the current skill → Move to the next skill ← Move to the previous skill Enter Move to the next skill (or submit when on the last skill) ? Open the keyboard shortcuts reference Esc Exit the assessment Select Continue to proceed to the assessment overview. Step 2: Assessment overview The second step shows a summary of your assessment: Card Description Deadline The date by which you must submit, and how many days remain Total Skills The number of skills you need to grade Est. Time An estimated time to complete (approximately 2 minutes per skill) Progress Your current completion percentage if you have already started Select Start Assessment to begin grading. If you have already started and are returning to continue, the button reads Continue Assessment . ​ Understanding the Grading Layout The assessment grading interface is divided into three areas: Area Purpose Left sidebar Skills list showing all skills grouped by job role, with completion status indicators Center content The current skill being graded, with the grading table and skill details Right sidebar Activity feed showing comments for the current skill The center content area shows: Skill title — Displayed as “[Section]: Skill Name” (for example, “Leadership: Team Management”) Skill description — A collapsible description of what the skill involves Labels — Any labels applied to the skill for categorization Progress counter — “X of Y graded” shown at the top right, updating after each grade The grading table in the center has the following columns: Column Description Grade Your self-assessed proficiency grade. Shows “Add Grade” until a grade is selected. Benchmark The expected proficiency level for this skill in your role (read-only). Prior grade Your grade from a previous assessment cycle, if one exists. N/A A toggle to mark the skill as Not Applicable. Focus A button to mark the skill as a development priority. Note: The Benchmark column only appears if a benchmark has been set for your role. The Prior grade column only appears if you have completed a previous assessment cycle. Your administrator controls the grading scale labels (for example, “Beginner” through “Expert”) for your organization. ​ Grading a Skill To grade a skill: In the Grade column, select Add Grade to open the grade selector. In the grade selector, choose the grade that best reflects your current proficiency level. Each grade option shows a short description (for example, “Proficient”) and a longer detail description. Select your chosen grade. The grade saves automatically and the Grade column updates to show your selection. The grade selector also shows a Benchmark badge next to the grade that matches your role’s expected level, and a Prior badge next to the grade that matches your previous assessment, so you can orient yourself before selecting. Tip: Use the keyboard shortcuts 1 – 5 to assign a grade instantly without opening the dropdown. This is the fastest way to move through a large assessment. When you select a grade, the progress counter increments and the skill in the left sidebar shows a checkmark indicating it has been graded. The Next button at the bottom of the page activates, allowing you to move to the next skill. ​ Marking a Skill as Not Applicable If a skill does not apply to your role or current work, you can mark it as Not Applicable instead of assigning a grade. To mark a skill as Not Applicable: In the N/A column, toggle the switch on. When a skill is marked Not Applicable --- ## Uploading Files URL: https://help.skillsdb.com/user-guide/uploading-files Quick Summary: The My Files page is your personal document library within SkillsDB. Upload supporting documents — such as resumes, training records, or certificates — organize them by type, and access them alongside your profile at any time. ​ Overview The My Files page gives you a dedicated space to store and manage personal documents within your SkillsDB profile. You can upload files such as resumes, training records, certificates, or any other documentation relevant to your skills and career development. All uploaded files are organized by document type, making them easy to find and reference. The My Files table shows each document’s name, who uploaded it, when it was uploaded, and its assigned document type. All SkillsDB users can access their My Files page and upload, preview, download, and delete their own files. No special permissions are required. ​ Navigating to My Files To open your files page Select Files from the left sidebar under the Profile section. The My Files page opens and displays all documents currently associated with your profile. If no files have been uploaded yet, the table appears empty. ​ Uploading files Use the Upload Files dialog to add one or more files to your profile. Select Files from the left sidebar. Select Upload File in the top-right corner of the page. The Upload Files dialog opens. Adding files to the dialog You can add files in one of two ways: Click to upload: Select the upload zone to open your file browser, then choose one or more files. Drag and drop: Drag files directly from your computer into the upload zone. You can add up to 5 files per upload session. As you add files, the dialog lists each filename, file size, and file type. To remove a file from the list before uploading, select the X icon next to it. Note: If you need to upload more than 5 files, complete the current upload first, then open the Upload Files dialog again to add more. Assigning a document type Every file requires a document type before it can be uploaded. New files default to Other when that type is available. Document types categorize your files and make them easier to organize and find later. For each file in the list, select the File type dropdown. Choose the category that best describes the file — for example, Resume, Certificate, or Training Record. Important: The File type field is required for every file in the list. Files cannot be uploaded until all document types are selected. If a type is missing, a message asks you to choose a file type before uploading. Completing the upload Once all files have a document type selected, select Upload Files . The button shows Uploading… while the files are being uploaded. When the upload is complete, the dialog closes and the new files appear in the My Files table. ​ Previewing a File To view a file without downloading it to your computer: Select Files from the left sidebar. In the My Files table, select the filename. A preview opens directly within SkillsDB. File preview is supported for common file types such as PDFs and images. If a file type cannot be previewed in the browser, SkillsDB will prompt you to download the file instead. ​ Downloading a File To save a copy of a file to your computer: Select Files from the left sidebar. In the My Files table, select the filename. Select Download in the preview footer. Select Close when you are finished. ​ Deleting a File To permanently remove a file from your profile: Select Files from the left sidebar. In the My Files table, locate the file you want to remove. Select the delete option for that file. In the confirmation dialog, confirm the deletion. When you delete a file, it is permanently removed from your profile and cannot be recovered. Warning: Deleting a file is permanent and cannot be undone. Download any files you may need before deleting them. ​ Filtering your files If you have many files uploaded, you can filter the My Files table by document type to find specific documents quickly. Select the Type filter in the table toolbar. Choose a document type from the dropdown. The table updates to show only files matching the selected type. To clear the filter and view all files, remove the selected type. ​ Common Questions What file types can I upload? SkillsDB accepts the following file types: .jpg , .jpeg , .png , .pdf , .docx , .xlsx , .txt , and .csv . Files in any other format will be rejected at the time of selection. If your file is in an unsupported format, convert it to one of the accepted types before uploading. What is the file size limit? Each individual file must be 10 MB or smaller. Files that exceed 10 MB are rejected when added to the upload dialog. If your file is too large, try compressing it or splitting the content across smaller files before uploading. How many files can I upload at once? You can add up to 5 files per upload session. There is no documented limit on the total number of files you can store in your profile. To upload more than 5 files, complete the first upload session and then open the Upload Files dialog again. Can I rename a file after uploading it? No. Files are stored under their original filename and cannot be renamed after upload. If you need a file with a different name, delete the existing file and re-upload it with the correct filename. Can I change the document type after uploading a file? No. Document types cannot be changed after a file has been uploaded. If you selected the wrong type, delete the file and re-upload it with the correct document type assigned. Who can see my uploaded files? Files you upload are part of your SkillsDB profile. Your manager and account administrators may have visibility into the files stored in your profile. What does the 'Uploaded by' column show? The Uploaded by column identifies the person who uploaded each file. In some cases, a manager or administrator may upload files on your behalf. This column records the original uploader for every file in your profile, regardless of who the file bel --- ## Your Skills Profile URL: https://help.skillsdb.com/user-guide/your-skills-profile Quick Summary: Your Skills Profile is your personal hub for tracking skill proficiency across your assigned careers, logging training, identifying focus areas, and discovering learning resources. ​ Overview Your Skills Profile gives you a complete picture of the skills SkillsDB tracks for you. It organizes your skills by the careers you have been assigned to, and surfaces key information like your self-assessed grades, manager grades, expected benchmarks, and training history. The Skills Profile is the primary place where you interact with your own skill data day-to-day. From here you can see how your proficiency compares to what your role requires, mark skills you want to focus on, log training records, and browse learning resources linked to your skills. All employees can access their own Skills Profile. Managers and administrators can also view team members’ profiles through the Team view, but this article covers what you can see and do on your own profile. ​ Navigating to Your Skills Profile To open your Skills Profile Select Skills from the left sidebar navigation. The Skills page opens and shows your profile overview. ​ Understanding the Skills Profile Layout The Skills page is divided into three views you can switch between using the breadcrumb dropdown at the top of the page: View Purpose By Career Your current skills profile — careers, highlights, and additional skills Upskilling Learning resources linked to your skills, with progress tracking Past Assignments Careers you were previously assigned to (read-only) The By Career view (shown by default) shows your current career assignments along with two summary entries: Entry What it shows Highlights Skills you or your manager have flagged for development Additional Skills Individual skills added outside of any career assignment Your careers are organized under collapsible group headers (for example, “Role”). Each career row shows the career name, a labels column, and the number of skills it contains. Note: Career group sections are collapsed or expanded by selecting the section header row. ​ Viewing skills for a career Selecting a career row opens the career detail view , which lists every skill in that career grouped by section. ​ Understanding the columns Column Description Skill The skill name. A short description may appear below the name if one has been added. Labels Any labels applied to this skill (used for categorisation). My Grade Your self-assessed proficiency grade on a 1–5 scale. Manager Your manager’s assessed grade on a 1–5 scale. Benchmark The expected proficiency level for this skill in your role. Resources The number of learning resources linked to this skill. Flags Any flags applied to this skill (Focus, Expert, Mentor, Interest, or custom flags). Note: The My Grade, Manager, and Benchmark columns only appear when proficiency grading is enabled for your career. You can show or hide columns using the Display button in the top right of the career detail view. Your administrator controls grading settings per career. ​ Reading grade indicators Grades are displayed as a numeric value (1–5) alongside a visual bar indicator: Green bars indicate a grade of 3 or higher (meeting or approaching benchmark). Red bars indicate a grade of 1 or 2 (below benchmark). Grey bars indicate a benchmark grade. If no grade has been recorded yet, the cell is blank. ​ Toggling skill sections Skills within a career are grouped into sections (for example, “Core Skills” or “Technical Skills”). Select a section header to collapse or expand that section. ​ Flagging a Skill Flagging a skill (for example, marking it as Focus) adds it to your Highlights view and signals to your manager that you are prioritising that skill. To flag a skill: Navigate to Skills in the sidebar. Select the career containing the skill you want to flag. In the Flags column, select the flag icon next to the skill and choose the flag type (for example, Focus). When you flag a skill, the flag indicator appears in the Flags column. Skills flagged as Focus also appear in your Highlights view. Tip: Use the Highlights view as a curated list of the skills you are actively working to improve. It is useful when preparing for assessments or conversations with your manager. ​ Adding Skills to Your Profile You can add individual skills to your profile using the + Skills button in the top right of the By Career view. Select + Skills to see the available options: Search library — browse the SkillsDB skill library and add existing skills to your Additional Skills. Request skill — submit a request for a new skill to be added to the library. Your administrator will review the request. Skills you add from the library appear in your Additional Skills entry. Requested skills are sent to your administrator for approval before they become available. Note: Administrators see an additional Add skill option that creates a new skill directly in the library. Standard users and managers see Request skill instead. ​ Viewing Highlights and Additional Skills In addition to viewing skills by career, two summary entries are available from the main By Career view. ​ Highlights Selecting Highlights shows only the skills you or your manager have flagged (for example, Focus flags). Use this view to concentrate your development activity on the skills that matter most right now. Flagged skills also appear in the Highlights section at the top of any career detail view. ​ Additional Skills Selecting Additional Skills shows individual skills that have been added to your profile outside of a formal career assignment. These may be skills you have added yourself or skills added by your manager. Additional skills display the same grade columns as career skills. ​ Logging a Training Record If your career has training tracking enabled, you can log a training record directly from your Skills Profile. To log a training record for a skill: Navigate to Skills in the sidebar. Select the career that contains the skill. In th ---