> ## Documentation Index
> Fetch the complete documentation index at: https://developers.techwolf.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# EIB Specification

This page covers the parts shared by every Workday EIB file: delivery,
dependencies, transformations and how to read the field tables. The files
themselves, with their fields and the Workday field each one comes from, are
described on the
[Jobs](/integrations/datasource-integrations/workday-datasource/jobs),
[Employees](/integrations/datasource-integrations/workday-datasource/employees)
and [Courses](/integrations/datasource-integrations/workday-datasource/courses)
pages.

## General specifications

The Workday EIB integration is file-based: Workday exports each file and
delivers it to the customer's TechWolf **AWS S3** bucket, from where TechWolf
reads it and syncs the data into the SkillEngine API. Setting up the custom
report and the Outbound EIB that delivers it is described in
[Installation](/integrations/datasource-integrations/workday-datasource/installation).

The base path for every file is:

```
s3://techwolf-<customer>/production/external/input/integrations/file_based/
```

<Note>
  During the testing phase, the `staging` environment path is used instead:
  `s3://techwolf-<customer>/staging/external/input/integrations/file_based/`.
</Note>

Each file has its own subfolder and naming pattern under that base path, given
per file on the Jobs, Employees and Courses pages. Files must be written into
those subfolders, not into the root of the file-based path. For the wider S3
layout, see [File Organization](/integrations/reference/file-structure).

The export **frequency is configured by the customer** and agreed with TechWolf
during implementation. It is set on the EIB schedule.

Each file is marked **Required**, **Highly recommended** or **Recommended**.
Required files must be delivered for the integration to work; the others add
skill-relevant signal and are delivered where the data exists.

## Shared rules

The following rules apply to every Workday file:

* All files are presumed to be full dumps, i.e. the state of all relevant
  entities is expected to be given in each export file, not just the changes
  compared to the last export.
* Not all files are necessarily required, though existing dependencies must be
  respected. For example, if the basic information of employees (i.e. their
  existence) is already synced, it is optional whether to include e.g. employee
  goals as well; yet when employee goals are to be synced, the employee baseline
  sync must be included as well. An overview of the dependencies is given below:

```mermaid theme={null}
erDiagram
    JOB_FAMILY["Job Family"] {
        string job_family_id PK
    }
    JOB["Job"] {
        string job_id PK
        string job_family_id FK
    }
    VACANCY["Vacancy (Job Requisition)"] {
        string requisition_id PK
        string job_id FK
    }
    COURSE["Course"] {
        string course_id PK
    }
    EMPLOYEE["Employee"] {
        string employee_id PK
        string assigned_position_id FK
        string organisational_unit_id FK
    }
    ORGANISATIONAL_UNIT["Organisational Unit"] {
        string organisational_unit_id PK
        string parent_organisational_unit_id FK
    }
    PERFORMANCE["Employee Performance"] {
        string employee_id FK
    }
    EXTERNAL_WORK_HISTORY["Employee External Work History"] {
        string employee_id FK
    }
    INTERNAL_WORK_HISTORY["Employee Internal Work History"] {
        string employee_id FK
        string job_id FK
    }
    EDUCATION_HISTORY["Employee Education History"] {
        string employee_id FK
    }
    CERTIFICATE["Employee Certification"] {
        string employee_id FK
    }
    FEEDBACK["Employee Feedback"] {
        string employee_id FK
    }
    GOAL["Employee Goal"] {
        string employee_id FK
    }
    LEARNING_HISTORY["Employee Learning History"] {
        string employee_id FK
        string course_id FK
    }
    RESUME["Employee Resume"] {
        string employee_id FK
    }

    JOB_FAMILY ||--o{ JOB : ""
    JOB ||--o{ VACANCY : ""
    JOB ||--o{ EMPLOYEE : ""
    JOB ||--o{ INTERNAL_WORK_HISTORY : ""
    COURSE ||--o{ LEARNING_HISTORY : ""
    EMPLOYEE ||--o{ EXTERNAL_WORK_HISTORY : ""
    EMPLOYEE ||--o{ INTERNAL_WORK_HISTORY : ""
    EMPLOYEE ||--o{ EDUCATION_HISTORY : ""
    EMPLOYEE ||--o{ CERTIFICATE : ""
    EMPLOYEE ||--o{ FEEDBACK : ""
    EMPLOYEE ||--o{ GOAL : ""
    EMPLOYEE ||--o{ LEARNING_HISTORY : ""
    EMPLOYEE ||--o{ RESUME : ""
    EMPLOYEE ||--o{ PERFORMANCE : ""
    ORGANISATIONAL_UNIT ||--o{ EMPLOYEE : ""
```

* All expected fields can be provided under another name, or split among
  different fields, as long as this division or rename is then used consistently
  (and is communicated to TechWolf). This applies to both the fields marked as
  "required" as those that are marked as "recommended". When multiple input
  fields are taken together to form one expected (or additional) field, the
  resulting field will consist of the values of the constituent fields,
  separated by a hyphen surrounded by spaces (" - "). Additionally, some field
  conversions are also supported; in particular, dates can be converted to the
  required format, and arbitrary string-to-string mappings can be configured,
  which can be particularly useful in combination with field filtering
  (mentioned below). Possible limitations specified on fields always apply after
  transformation.
* Fields that are marked as "required" are generally expected to always be
  present (after transformation). However, there is also support for "default
  values", though this only applies to certain fields (marked with \*). Setting
  defaults should be avoided, since it makes data less informative, and should
  only be used in cases where it is unavoidable and doesn't cause unnecessary
  obfuscation or decreased informativeness. One use case could be to set all
  certificate descriptions to be "-" by default if no actual certificate
  descriptions are available, but the certificate titles are still informative
  enough to warrant syncing certificates.
* The integrations support field filters: per input file, one field can be
  chosen to act as a filter (besides possibly also carrying information to be
  synced), where the input object (csv row, xlsx row, ...) is only processed if
  the value of the filter field is either contained in the given whitelist of
  values or not included in the given banlist of values. Note that filtering is
  completely optional and that filtering is applied after input transformation.
  Do note that TechWolf always prefers filtering at the EIB where possible, to
  prevent unnecessary data transfer and processing.

<Card title="slugify" icon="worm" iconType="solid">
  Slug strings are strings consisting of only lowercase letters, uppercase
  letters, numbers, underscores (\_) and dashes (-).

  When non-slug strings are slugified at TechWolf's side, we use a mapping as
  defined in
  [slugify](https://github.com/simov/slugify/blob/master/config/charmap.json),
  except for the following mappings:

  * "/" becomes "\_SLASH\_"
  * "(" becomes "\_OPENR\_"
  * ")" becomes "\_CLOSER\_"
  * "\[" becomes "\_OPENS\_"
  * "]" becomes "\_CLOSES\_"
  * "\{" becomes "\_OPENC\_"
  * "}" becomes "\_CLOSEC\_"
</Card>

## Reading the field tables

Each file on the Jobs, Employees and Courses pages has one table, with one row
per Workday field:

* **TechWolf field** is the column name TechWolf expects in the file.
* **Primary Business Object**, **Business Object** and **Workday field** give
  the full path to the field in Workday: the business object the report is built
  on, the related business object the field sits on, and the field itself. A
  field whose name starts with `CF` is a calculated field.
* When a TechWolf field is listed on several rows, the Workday fields on those
  rows are joined into one value, separated by `" - "`.
* **Required** is `Required` or `Recommended`. A `Required` field must have a
  value on every row. A `Recommended` field can be left empty, but send it
  wherever Workday holds a value. `Required*` means the field supports a default
  value (see the notes above).
* **Key** marks the external ID of the file (`Primary key`) and fields that
  point to the primary key of another file (`Foreign key`). Fields without a Key
  are data fields used for skill inference or context.
* **Max chars** gives the longest value the SkillEngine API accepts for that
  field, measured after transformation. A row whose value exceeds the limit is
  rejected on ingest, so over-long values should be truncated or dropped in the
  EIB rather than left for the integration to reject. `No limit` means the API
  sets no maximum; `n/a` means the field is not free text (a date, a boolean or
  a number).
* `n/a` in the Workday columns means there is no default Workday field; the
  source, if any, is agreed with TechWolf during implementation.

## Profile data and custom properties

Job Families and Jobs can be extended with an arbitrary amount of "profile
data", which will be used for skill extraction. The profile data types available
are:

* Job Families: `job_family_description`
* Jobs: `job_description`, `job_title`, `vacancy`, `skill_notes`

For every profile data variant, we need the following information:

* The name of the source field(s) in the input (and their ordering, in case of
  concatenation)
* The profile data type
* Whether the profile data should always be present (true or false)

Job Families, Jobs, Vacancies, Courses and Employees can also be extended with
an arbitrary amount of "custom properties", which will NOT be used for skill
extraction, but might be useful for querying or other identification, grouping
or disambiguation scenarios. For every custom property, we need the following
information:

* The name of the source field(s) in the input (and their ordering, in case of
  concatenation)
* The name of the custom property (at least 1 and at most 100 characters; cannot
  contain "\_\_")
* The data type of the custom property ("text", "number", "boolean",
  "list\[text]" or "datetime")
* Whether the custom property should always be present (true or false)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.